Remove instances of unused 'data_handle' (and of one other handle).
[metze/wireshark/wip.git] / epan / dissectors / packet-bacapp.c
1 /* packet-bacapp.c
2  * Routines for BACnet (APDU) dissection
3  * Copyright 2001, Hartmut Mueller <hartmut[AT]abmlinux.org>, FH Dortmund
4  * Enhanced by Steve Karg, 2005, <skarg[AT]users.sourceforge.net>, Atlanta
5  * Enhanced by Herbert Lischka, 2005, <lischka[AT]kieback-peter.de>, Berlin
6  * Enhanced by Felix Kraemer, 2010, <sauter-cumulus[AT]de.sauter-bc.com>,
7  *  Sauter-Cumulus GmbH, Freiburg
8  *
9  * $Id$
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald[AT]wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28  */
29
30 #include "config.h"
31
32 #include <glib.h>
33
34 #include <epan/packet.h>
35 #include <epan/wmem/wmem.h>
36 #include <epan/reassemble.h>
37 #include <epan/expert.h>
38 #include <epan/stats_tree.h>
39 #include "packet-bacapp.h"
40
41 static int bacapp_tap = -1;
42
43 /* formerly bacapp.h  contains definitions and forward declarations */
44
45 #ifndef FAULT
46 #define FAULT           proto_tree_add_text(subtree, tvb, offset, tvb_length(tvb) - offset, "something is going wrong here !!"); \
47     offset = tvb_length(tvb);
48 #endif
49
50 /* BACnet PDU Types */
51 #define BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST                   0
52 #define BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST                 1
53 #define BACAPP_TYPE_SIMPLE_ACK                                  2
54 #define BACAPP_TYPE_COMPLEX_ACK                                 3
55 #define BACAPP_TYPE_SEGMENT_ACK                                 4
56 #define BACAPP_TYPE_ERROR                                       5
57 #define BACAPP_TYPE_REJECT                                      6
58 #define BACAPP_TYPE_ABORT                                       7
59 #define MAX_BACAPP_TYPE                                         8
60
61 #define BACAPP_SEGMENTED_REQUEST 0x08
62 #define BACAPP_MORE_SEGMENTS 0x04
63 #define BACAPP_SEGMENTED_RESPONSE 0x02
64 #define BACAPP_SEGMENT_NAK 0x02
65 #define BACAPP_SENT_BY 0x01
66
67
68 /**
69  * dissect_bacapp ::= CHOICE {
70  *  confirmed-request-PDU       [0] BACnet-Confirmed-Request-PDU,
71  *  unconfirmed-request-PDU     [1] BACnet-Unconfirmed-Request-PDU,
72  *  simpleACK-PDU               [2] BACnet-SimpleACK-PDU,
73  *  complexACK-PDU              [3] BACnet-ComplexACK-PDU,
74  *  segmentACK-PDU              [4] BACnet-SegmentACK-PDU,
75  *  error-PDU                   [5] BACnet-Error-PDU,
76  *  reject-PDU                  [6] BACnet-Reject-PDU,
77  *  abort-PDU                   [7] BACnet-Abort-PDU
78  * }
79  * @param tvb the tv buffer of the current data
80  * @param pinfo the packet info of the current data
81  * @param tree the tree to append this item to
82  **/
83 static void
84 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
85
86 /**
87  * ConfirmedRequest-PDU ::= SEQUENCE {
88  *  pdu-type                    [0] Unsigned (0..15), -- 0 for this PDU Type
89  *  segmentedMessage            [1] BOOLEAN,
90  *  moreFollows                 [2] BOOLEAN,
91  *  segmented-response-accepted [3] BOOLEAN,
92  *  reserved                    [4] Unsigned (0..3), -- must be set zero
93  *  max-segments-accepted       [5] Unsigned (0..7), -- as per 20.1.2.4
94  *  max-APDU-length-accepted    [5] Unsigned (0..15), -- as per 20.1.2.5
95  *  invokeID                    [6] Unsigned (0..255),
96  *  sequence-number             [7] Unsigned (0..255) OPTIONAL, -- only if segmented msg
97  *  proposed-window-size        [8] Unsigned (0..127) OPTIONAL, -- only if segmented msg
98  *  service-choice              [9] BACnetConfirmedServiceChoice,
99  *  service-request             [10] BACnet-Confirmed-Service-Request OPTIONAL
100  * }
101  * @param tvb the tv buffer of the current data
102  * @param pinfo the packet info of the current data
103  * @param tree the tree to append this item to
104  * @param offset the offset in the tvb
105  * @return modified offset
106  */
107 static guint
108 fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
109
110 /**
111  * @param tvb the tv buffer of the current data
112  * @param pinfo the packet info of the current data
113  * @param tree the tree to append this item to
114  * @param offset the offset in the tvb
115  * @param ack - indocates whether working on request or ack
116  * @param svc - output variable to return service choice
117  * @param tt  - output varable to return service choice item
118  * @return modified offset
119  */
120 static guint
121 fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 ack,
122                 gint *svc, proto_item **tt);
123
124 /**
125  * Unconfirmed-Request-PDU ::= SEQUENCE {
126  *  pdu-type        [0] Unsigned (0..15), -- 1 for this PDU type
127  *  reserved        [1] Unsigned (0..15), -- must be set zero
128  *  service-choice  [2] BACnetUnconfirmedServiceChoice,
129  *  service-request [3] BACnetUnconfirmedServiceRequest -- Context-specific tags 0..3 are NOT used in header encoding
130  * }
131  * @param tvb the tv buffer of the current data
132  * @param pinfo the packet info of the current data
133  * @param tree the tree to append this item to
134  * @param offset the offset in the tvb
135  * @return modified offset
136  */
137 static guint
138 fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
139
140 /**
141  * SimpleACK-PDU ::= SEQUENCE {
142  *  pdu-type            [0] Unsigned (0..15), -- 2 for this PDU type
143  *  reserved            [1] Unsigned (0..15), -- must be set zero
144  *  invokeID            [2] Unsigned (0..255),
145  *  service-ACK-choice  [3] BACnetUnconfirmedServiceChoice -- Context-specific tags 0..3 are NOT used in header encoding
146  * }
147  * @param tvb the tv buffer of the current data
148  * @param pinfo the packet info of the current data
149  * @param tree the tree to append this item to
150  * @param offset the offset in the tvb
151  * @return modified offset
152  */
153 static guint
154 fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
155
156 /**
157  * ComplexACK-PDU ::= SEQUENCE {
158  *  pdu-type                [0] Unsigned (0..15), -- 3 for this PDU Type
159  *  segmentedMessage        [1] BOOLEAN,
160  *  moreFollows             [2] BOOLEAN,
161  *  reserved                [3] Unsigned (0..3), -- must be set zero
162  *  invokeID                [4] Unsigned (0..255),
163  *  sequence-number         [5] Unsigned (0..255) OPTIONAL, -- only if segmented msg
164  *  proposed-window-size    [6] Unsigned (0..127) OPTIONAL, -- only if segmented msg
165  *  service-ACK-choice      [7] BACnetConfirmedServiceChoice,
166  *  service-ACK             [8] BACnet-Confirmed-Service-Request  -- Context-specific tags 0..8 are NOT used in header encoding
167  * }
168  * @param tvb the tv buffer of the current data
169  * @param pinfo the packet info of the current data
170  * @param tree the tree to append this item to
171  * @param offset the offset in the tvb
172  * @return modified offset
173  */
174 static guint
175 fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
176
177 /**
178  * SegmentACK-PDU ::= SEQUENCE {
179  *  pdu-type                [0] Unsigned (0..15), -- 4 for this PDU Type
180  *  reserved                [1] Unsigned (0..3), -- must be set zero
181  *  negative-ACK            [2] BOOLEAN,
182  *  server                  [3] BOOLEAN,
183  *  original-invokeID       [4] Unsigned (0..255),
184  *  sequence-number         [5] Unsigned (0..255),
185  *  actual-window-size      [6] Unsigned (0..127)
186  * }
187  * @param tvb the tv buffer of the current data
188  * @param pinfo the packet info of the current data
189  * @param tree the tree to append this item to
190  * @param offset the offset in the tvb
191  * @return modified offset
192  */
193 static guint
194 fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
195
196 /**
197  * Error-PDU ::= SEQUENCE {
198  *  pdu-type                [0] Unsigned (0..15), -- 5 for this PDU Type
199  *  reserved                [1] Unsigned (0..3), -- must be set zero
200  *  original-invokeID       [2] Unsigned (0..255),
201  *  error-choice            [3] BACnetConfirmedServiceChoice,
202  *  error                   [4] BACnet-Error
203  * }
204  * @param tvb the tv buffer of the current data
205  * @param pinfo the packet info of the current data
206  * @param tree the tree to append this item to
207  * @param offset the offset in the tvb
208  * @return modified offset
209  */
210 static guint
211 fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
212
213 /**
214  * Reject-PDU ::= SEQUENCE {
215  *  pdu-type                [0] Unsigned (0..15), -- 6 for this PDU Type
216  *  reserved                [1] Unsigned (0..3), -- must be set zero
217  *  original-invokeID       [2] Unsigned (0..255),
218  *  reject-reason           [3] BACnetRejectReason
219  * }
220  * @param tvb the tv buffer of the current data
221  * @param pinfo the packet info of the current data
222  * @param tree the tree to append this item to
223  * @param offset the offset in the tvb
224  * @return modified offset
225  */
226 static guint
227 fRejectPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
228
229 /**
230  * Abort-PDU ::= SEQUENCE {
231  *  pdu-type                [0] Unsigned (0..15), -- 7 for this PDU Type
232  *  reserved                [1] Unsigned (0..3), -- must be set zero
233  *  server                  [2] BOOLEAN,
234  *  original-invokeID       [3] Unsigned (0..255),
235  *  abort-reason            [4] BACnetAbortReason
236  * }
237  * @param tvb the tv buffer of the current data
238  * @param pinfo the packet info of the current data
239  * @param tree the tree to append this item to
240  * @param offset the offset in the tvb
241  * @return modified offset
242  */
243 static guint
244 fAbortPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
245
246 /**
247  * 20.2.4, adds the label with max 64Bit unsigned Integer Value to tree
248  * @param tvb the tv buffer of the current data
249  * @param pinfo the packet info of the current data
250  * @param tree the tree to append this item to
251  * @param offset the offset in the tvb
252  * @param label the label of this item
253  * @return modified offset
254  */
255 static guint
256 fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
257
258 /**
259  * 20.2.5, adds the label with max 64Bit signed Integer Value to tree
260  * @param tvb the tv buffer of the current data
261  * @param pinfo the packet info of the current data
262  * @param tree the tree to append this item to
263  * @param offset the offset in the tvb
264  * @param label the label of this item
265  * @return modified offset
266  */
267 static guint
268 fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
269
270 /**
271  * 20.2.8, adds the label with Octet String to tree; if lvt == 0 then lvt = restOfFrame
272  * @param tvb the tv buffer of the current data
273  * @param pinfo the packet info of the current data
274  * @param tree the tree to append this item to
275  * @param offset the offset in the tvb
276  * @param label the label of this item
277  * @param lvt length of String
278  * @return modified offset
279  */
280 static guint
281 fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt);
282
283 /**
284  * 20.2.12, adds the label with Date Value to tree
285  * @param tvb the tv buffer of the current data
286  * @param pinfo the packet info of the current data
287  * @param tree the tree to append this item to
288  * @param offset the offset in the tvb
289  * @param label the label of this item
290  * @return modified offset
291  */
292 static guint
293 fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
294
295 /**
296  * 20.2.13, adds the label with Time Value to tree
297  * @param tvb the tv buffer of the current data
298  * @param pinfo the packet info of the current data
299  * @param tree the tree to append this item to
300  * @param offset the offset in the tvb
301  * @param label the label of this item
302  * @return modified offset
303  */
304 static guint
305 fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
306
307 /**
308  * 20.2.14, adds Object Identifier to tree
309  * use BIG ENDIAN: Bits 31..22 Object Type, Bits 21..0 Instance Number
310  * @param tvb the tv buffer of the current data
311  * @param pinfo the packet info of the current data
312  * @param tree the tree to append this item to
313  * @param offset the offset in the tvb
314  * @return modified offset
315  */
316 static guint
317 fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
318
319 /**
320  * BACnet-Confirmed-Service-Request ::= CHOICE {
321  * }
322  * @param tvb the tv buffer of the current data
323  * @param pinfo the packet info of the current data
324  * @param tree the tree to append this item to
325  * @param offset the offset in the tvb
326  * @param service_choice the service choice
327  * @return offset
328  */
329 static guint
330 fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
331
332 /**
333  * BACnet-Confirmed-Service-ACK ::= CHOICE {
334  * }
335  * @param tvb the tv buffer of the current data
336  * @param pinfo the packet info of the current data
337  * @param tree the tree to append this item to
338  * @param offset the offset in the tvb
339  * @param service_choice the service choice
340  * @return offset
341  */
342 static guint
343 fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
344
345 /**
346  * AcknowledgeAlarm-Request ::= SEQUENCE {
347  *  acknowledgingProcessIdentifier [0] Unsigned32,
348  *  eventObjectIdentifier          [1] BACnetObjectIdentifer,
349  *  eventStateAcknowledge          [2] BACnetEventState,
350  *  timeStamp                      [3] BACnetTimeStamp,
351  *  acknowledgementSource          [4] Character String,
352  *  timeOfAcknowledgement          [5] BACnetTimeStamp
353  * }
354  * @param tvb the tv buffer of the current data
355  * @param pinfo the packet info of the current data
356  * @param tree the tree to append this item to
357  * @param offset the offset in the tvb
358  * @return modified offset
359  */
360 static guint
361 fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
362
363 /**
364  * ConfirmedCOVNotification-Request ::= SEQUENCE {
365  *  subscriberProcessIdentifier [0] Unsigned32,
366  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
367  *  monitoredObjectIdentifier   [2] BACnetObjectIdentifer,
368  *  timeRemaining               [3] unsigned,
369  *  listOfValues                [4] SEQUENCE OF BACnetPropertyValues
370  * }
371  * @param tvb the tv buffer of the current data
372  * @param pinfo the packet info of the current data
373  * @param tree the tree to append this item to
374  * @param offset the offset in the tvb
375  * @return modified offset
376  */
377 static guint
378 fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
379
380 /**
381  * ConfirmedEventNotification-Request ::= SEQUENCE {
382  *  ProcessIdentifier           [0] Unsigned32,
383  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
384  *  eventObjectIdentifier       [2] BACnetObjectIdentifer,
385  *  timeStamp                   [3] BACnetTimeStamp,
386  *  notificationClass           [4] unsigned,
387  *  priority                    [5] unsigned8,
388  *  eventType                   [6] BACnetEventType,
389  *  messageText                 [7] CharacterString OPTIONAL,
390  *  notifyType                  [8] BACnetNotifyType,
391  *  ackRequired                 [9] BOOLEAN OPTIONAL,
392  *  fromState                  [10] BACnetEventState OPTIONAL,
393  *  toState                    [11] BACnetEventState,
394  *  eventValues                [12] BACnetNotificationParameters OPTIONAL
395  * }
396  * @param tvb the tv buffer of the current data
397  * @param pinfo the packet info of the current data
398  * @param tree the tree to append this item to
399  * @param offset the offset in the tvb
400  * @return modified offset
401  */
402 static guint
403 fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo,  proto_tree *tree, guint offset);
404
405 /**
406  * GetAlarmSummary-ACK ::= SEQUENCE OF SEQUENCE {
407  *  objectIdentifier         BACnetObjectIdentifer,
408  *  alarmState               BACnetEventState,
409  *  acknowledgedTransitions  BACnetEventTransitionBits
410  * }
411  * @param tvb the tv buffer of the current data
412  * @param pinfo the packet info of the current data
413  * @param tree the tree to append this item to
414  * @param offset the offset in the tvb
415  * @return modified offset
416  */
417 static guint
418 fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
419
420 /**
421  * GetEnrollmentSummary-Request ::= SEQUENCE {
422  *  acknowledgmentFilter    [0] ENUMERATED {
423  *      all       (0),
424  *      acked     (1),
425  *      not-acked (2)
426  *      },
427  *  enrollmentFilter        [1] BACnetRecipientProcess OPTIONAL,
428  *  eventStateFilter        [2] ENUMERATED {
429  *      offnormal (0),
430  *      fault     (1),
431  *      normal    (2),
432  *      all       (3),
433  *      active    (4)
434  *      },
435  *  eventTypeFilter         [3] BACnetEventType OPTIONAL,
436  *  priorityFilter          [4] SEQUENCE {
437  *      minPriority [0] Unsigned8,
438  *      maxPriority [1] Unsigned8
439  *      } OPTIONAL,
440  *  notificationClassFilter [5] Unsigned OPTIONAL
441  * }
442  * @param tvb the tv buffer of the current data
443  * @param pinfo the packet info of the current data
444  * @param tree the tree to append this item to
445  * @param offset the offset in the tvb
446  * @return modified offset
447  */
448 static guint
449 fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
450
451 /**
452  * GetEnrollmentSummary-ACK ::= SEQUENCE OF SEQUENCE {
453  *  objectIdentifier    BACnetObjectIdentifer,
454  *  eventType           BACnetEventType,
455  *  eventState          BACnetEventState,
456  *  priority            Unsigned8,
457  *  notificationClass   Unsigned OPTIONAL
458  * }
459  * @param tvb the tv buffer of the current data
460  * @param pinfo the packet info of the current data
461  * @param tree the tree to append this item to
462  * @param offset the offset in the tvb
463  * @return modified offset
464  */
465 static guint
466 fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
467
468 /**
469  * GetEventInformation-Request ::= SEQUENCE {
470  *  lastReceivedObjectIdentifier    [0] BACnetObjectIdentifer
471  * }
472  * @param tvb the tv buffer of the current data
473  * @param pinfo the packet info of the current data
474  * @param tree the tree to append this item to
475  * @param offset the offset in the tvb
476  * @return modified offset
477  */
478 static guint
479 fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
480
481 /**
482  * GetEventInformation-ACK ::= SEQUENCE {
483  *  listOfEventSummaries [0] listOfEventSummaries,
484  *  moreEvents           [1] BOOLEAN
485  * }
486  * @param tvb the tv buffer of the current data
487  * @param pinfo the packet info of the current data
488  * @param tree the tree to append this item to
489  * @param offset the offset in the tvb
490  * @return modified offset
491  */
492 static guint
493 fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
494
495 /**
496  * LifeSafetyOperation-Request ::= SEQUENCE {
497  *  requestingProcessIdentifier [0] Unsigned32
498  *  requestingSource            [1] CharacterString
499  *  request                     [2] BACnetLifeSafetyOperation
500  *  objectIdentifier            [3] BACnetObjectIdentifier OPTIONAL
501  * }
502  * @param tvb the tv buffer of the current data
503  * @param pinfo the packet info of the current data
504  * @param tree the tree to append this item to
505  * @param offset the offset in the tvb
506  * @return modified offset
507  */
508 static guint
509 fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
510
511 /**
512  * SubscribeCOV-Request ::= SEQUENCE {
513  *  subscriberProcessIdentifier [0] Unsigned32
514  *  monitoredObjectIdentifier   [1] BACnetObjectIdentifier
515  *  issueConfirmedNotifications [2] BOOLEAN OPTIONAL
516  *  lifetime                    [3] Unsigned OPTIONAL
517  * }
518  * @param tvb the tv buffer of the current data
519  * @param pinfo the packet info of the current data
520  * @param tree the tree to append this item to
521  * @param offset the offset in the tvb
522  * @return modified offset
523  */
524 static guint
525 fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
526
527 /**
528  * SubscribeCOVProperty-Request ::= SEQUENCE {
529  *  subscriberProcessIdentifier [0] Unsigned32
530  *  monitoredObjectIdentifier   [1] BACnetObjectIdentifier
531  *  issueConfirmedNotifications [2] BOOLEAN OPTIONAL
532  *  lifetime                    [3] Unsigned OPTIONAL
533  *  monitoredPropertyIdentifier [4] BACnetPropertyReference OPTIONAL
534  *  covIncrement                [5] Unsigned OPTIONAL
535  * }
536  * @param tvb the tv buffer of the current data
537  * @param pinfo the packet info of the current data
538  * @param tree the tree to append this item to
539  * @param offset the offset in the tvb
540  * @return modified offset
541  */
542 static guint
543 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
544
545 /**
546  * AtomicReadFile-Request ::= SEQUENCE {
547  *  fileIdentifier  BACnetObjectIdentifier,
548  *  accessMethod    CHOICE {
549  *      streamAccess    [0] SEQUENCE {
550  *          fileStartPosition   INTEGER,
551  *          requestedOctetCount Unsigned
552  *          },
553  *      recordAccess    [1] SEQUENCE {
554  *          fileStartRecord      INTEGER,
555  *          requestedRecordCount Unsigned
556  *          }
557  *      }
558  * }
559  * @param tvb the tv buffer of the current data
560  * @param pinfo the packet info of the current data
561  * @param tree the tree to append this item to
562  * @param offset the offset in the tvb
563  * @return modified offset
564  */
565 static guint
566 fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
567
568 /**
569  * AtomicWriteFile-ACK ::= SEQUENCE {
570  *  endOfFile   BOOLEAN,
571  *  accessMethod    CHOICE {
572  *      streamAccess    [0] SEQUENCE {
573  *          fileStartPosition   INTEGER,
574  *          fileData            OCTET STRING
575  *          },
576  *      recordAccess    [1] SEQUENCE {
577  *          fileStartRecord     INTEGER,
578  *          returnedRecordCount Unsigned,
579  *          fileRecordData      SEQUENCE OF OCTET STRING
580  *          }
581  *      }
582  * }
583  * @param tvb the tv buffer of the current data
584  * @param pinfo the packet info of the current data
585  * @param tree the tree to append this item to
586  * @param offset the offset in the tvb
587  * @return modified offset
588  */
589 static guint
590 fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
591
592 /**
593  * AtomicWriteFile-Request ::= SEQUENCE {
594  *  fileIdentifier  BACnetObjectIdentifier,
595  *  accessMethod    CHOICE {
596  *      streamAccess    [0] SEQUENCE {
597  *          fileStartPosition  INTEGER,
598  *          fileData           OCTET STRING
599  *          },
600  *      recordAccess    [1] SEQUENCE {
601  *          fileStartRecord    INTEGER,
602  *          recordCount        Unsigned,
603  *          fileRecordData     SEQUENCE OF OCTET STRING
604  *          }
605  *      }
606  * }
607  * @param tvb the tv buffer of the current data
608  * @param pinfo the packet info of the current data
609  * @param tree the tree to append this item to
610  * @param offset the offset in the tvb
611  * @return modified offset
612  */
613 static guint
614 fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
615
616 /**
617  * AtomicWriteFile-ACK ::= SEQUENCE {
618  *      fileStartPosition [0] INTEGER,
619  *      fileStartRecord   [1] INTEGER,
620  * }
621  * @param tvb the tv buffer of the current data
622  * @param pinfo the packet info of the current data
623  * @param tree the tree to append this item to
624  * @param offset the offset in the tvb
625  * @return modified offset
626  */
627 static guint
628 fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
629
630 /**
631  * AddListElement-Request ::= SEQUENCE {
632  *  objectIdentifier   [0] BACnetObjectIdentifier,
633  *  propertyIdentifier [1] BACnetPropertyIdentifier,
634  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
635  *  listOfElements     [3] ABSTRACT-SYNTAX.&Type
636  * }
637  * @param tvb the tv buffer of the current data
638  * @param pinfo the packet info of the current data
639  * @param tree the tree to append this item to
640  * @param offset the offset in the tvb
641  * @return modified offset
642  */
643 static guint
644 fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
645
646 /**
647  * CreateObject-Request ::= SEQUENCE {
648  *  objectSpecifier     [0] ObjectSpecifier,
649  *  listOfInitialValues [1] SEQUENCE OF BACnetPropertyValue OPTIONAL
650  * }
651  * @param tvb the tv buffer of the current data
652  * @param pinfo the packet info of the current data
653  * @param subtree the sub tree to append this item to
654  * @param offset the offset in the tvb
655  * @return modified offset
656  */
657 static guint
658 fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
659
660 /**
661  * CreateObject-Request ::= BACnetObjectIdentifier
662  * @param tvb the tv buffer of the current data
663  * @param pinfo the packet info of the current data
664  * @param tree the tree to append this item to
665  * @param offset the offset in the tvb
666  * @return modified offset
667  */
668 static guint
669 fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
670
671 /**
672  * DeleteObject-Request ::= SEQUENCE {
673  *  ObjectIdentifier    BACnetObjectIdentifer
674  * }
675  * @param tvb the tv buffer of the current data
676  * @param pinfo the packet info of the current data
677  * @param tree the tree to append this item to
678  * @param offset the offset in the tvb
679  * @return modified offset
680  */
681 static guint
682 fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
683
684 /**
685  * ReadProperty-Request ::= SEQUENCE {
686  *  objectIdentifier    [0] BACnetObjectIdentifier,
687  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
688  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
689  * }
690  * @param tvb the tv buffer of the current data
691  * @param pinfo the packet info of the current data
692  * @param tree the tree to append this item to
693  * @param offset the offset in the tvb
694  * @return modified offset
695  */
696 static guint
697 fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
698
699 /**
700  * ReadProperty-ACK ::= SEQUENCE {
701  *  objectIdentifier   [0] BACnetObjectIdentifier,
702  *  propertyIdentifier [1] BACnetPropertyIdentifier,
703  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
704  *  propertyValue      [3] ABSTRACT-SYNTAX.&Type
705  * }
706  * @param tvb the tv buffer of the current data
707  * @param pinfo the packet info of the current data
708  * @param tree the tree to append this item to
709  * @param offset the offset in the tvb
710  * @return modified offset
711  */
712 static guint
713 fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
714
715 /**
716  * ReadPropertyConditional-Request ::= SEQUENCE {
717  *  objectSelectionCriteria  [0] objectSelectionCriteria,
718  *  listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference OPTIONAL
719  * }
720  * @param tvb the tv buffer of the current data
721  * @param pinfo the packet info of the current data
722  * @param subtree the  sub tree to append this item to
723  * @param offset the offset in the tvb
724  * @return modified offset
725  */
726 static guint
727 fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
728
729 /**
730  * ReadPropertyConditional-ACK ::= SEQUENCE {
731  *  listOfPReadAccessResults    SEQUENCE OF ReadAccessResult OPTIONAL
732  * }
733  * @param tvb the tv buffer of the current data
734  * @param pinfo the packet info of the current data
735  * @param tree the tree to append this item to
736  * @param offset the offset in the tvb
737  * @return modified offset
738  */
739 static guint
740 fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
741
742 /**
743  * ReadPropertyMultiple-Request ::= SEQUENCE {
744  *  listOfReadAccessSpecs   SEQUENCE OF ReadAccessSpecification
745  * }
746  * @param tvb the tv buffer of the current data
747  * @param pinfo the packet info of the current data
748  * @param subtree the sub tree to append this item to
749  * @param offset the offset in the tvb
750  * @return offset modified
751  */
752 static guint
753 fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
754
755 /**
756  * ReadPropertyMultiple-Ack ::= SEQUENCE {
757  *  listOfReadAccessResults SEQUENCE OF ReadAccessResult
758  * }
759  * @param tvb the tv buffer of the current data
760  * @parma pinfo
761  * @param tree the tree to append this item to
762  * @param offset the offset in the tvb
763  * @return offset modified
764  */
765 static guint
766 fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
767
768 /**
769  * ReadRange-Request ::= SEQUENCE {
770  *  objectIdentifier    [0] BACnetObjectIdentifier,
771  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
772  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
773  *  range   CHOICE {
774  *      byPosition  [3] SEQUENCE {
775  *          referencedIndex Unsigned,
776  *          count INTEGER
777  *          },
778  *      byTime      [4] SEQUENCE {
779  *          referenceTime BACnetDateTime,
780  *          count INTEGER
781  *          },
782  *      timeRange   [5] SEQUENCE {
783  *          beginningTime BACnetDateTime,
784  *          endingTime BACnetDateTime
785  *          },
786  *      } OPTIONAL
787  * }
788  * @param tvb the tv buffer of the current data
789  * @param pinfo the packet info of the current data
790  * @param tree the tree to append this item to
791  * @param offset the offset in the tvb
792  * @return modified offset
793  */
794 static guint
795 fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
796
797 /**
798  * ReadRange-ACK ::= SEQUENCE {
799  *  objectIdentifier   [0] BACnetObjectIdentifier,
800  *  propertyIdentifier [1] BACnetPropertyIdentifier,
801  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
802  *  resultFlags        [3] BACnetResultFlags,
803  *  itemCount          [4] Unsigned,
804  *  itemData           [5] SEQUENCE OF ABSTRACT-SYNTAX.&Type
805  * }
806  * @param tvb the tv buffer of the current data
807  * @param pinfo the packet info of the current data
808  * @param tree the tree to append this item to
809  * @param offset the offset in the tvb
810  * @return modified offset
811  */
812 static guint
813 fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
814
815 /**
816  * RemoveListElement-Request ::= SEQUENCE {
817  *  objectIdentifier    [0] BACnetObjectIdentifier,
818  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
819  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
820  *  listOfElements  [3] ABSTRACT-SYNTAX.&Type
821  * }
822  * @param tvb the tv buffer of the current data
823  * @param pinfo the packet info of the current data
824  * @param tree the tree to append this item to
825  * @param offset the offset in the tvb
826  * @return modified offset
827  */
828 static guint
829 fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
830
831 /**
832  * WriteProperty-Request ::= SEQUENCE {
833  *  objectIdentifier   [0] BACnetObjectIdentifier,
834  *  propertyIdentifier [1] BACnetPropertyIdentifier,
835  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
836  *  propertyValue      [3] ABSTRACT-SYNTAX.&Type
837  *  priority           [4] Unsigned8 (1..16) OPTIONAL --used only when property is commandable
838  * }
839  * @param tvb the tv buffer of the current data
840  * @param pinfo the packet info of the current data
841  * @param tree the tree to append this item to
842  * @param offset the offset in the tvb
843  * @return modified offset
844  */
845 static guint
846 fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
847
848 /**
849  * WritePropertyMultiple-Request ::= SEQUENCE {
850  *  listOfWriteAccessSpecifications SEQUENCE OF WriteAccessSpecification
851  * }
852  * @param tvb the tv buffer of the current data
853  * @param pinfo the packet info of the current data
854  * @param tree the tree to append this item to
855  * @param offset the offset in the tvb
856  * @return modified offset
857  */
858 static guint
859 fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
860
861 /**
862  * DeviceCommunicationControl-Request ::= SEQUENCE {
863  *  timeDuration    [0] Unsigned16 OPTIONAL,
864  *  enable-disable  [1] ENUMERATED {
865  *      enable  (0),
866  *      disable (1)
867  *      },
868  *  password        [2] CharacterString (SIZE(1..20)) OPTIONAL
869  * }
870  * @param tvb the tv buffer of the current data
871  * @param pinfo the packet info of the current data
872  * @param tree the tree to append this item to
873  * @param offset the offset in the tvb
874  * @return modified offset
875  */
876 static guint
877 fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
878
879 /**
880  * ConfirmedPrivateTransfer-Request ::= SEQUENCE {
881  *  vendorID          [0] Unsigned,
882  *  serviceNumber     [1] Unsigned,
883  *  serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
884  * }
885  * @param tvb the tv buffer of the current data
886  * @param pinfo the packet info of the current data
887  * @param tree the tree to append this item to
888  * @param offset the offset in the tvb
889  * @return modified offset
890  */
891 static guint
892 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
893
894 /**
895  * ConfirmedPrivateTransfer-ACK ::= SEQUENCE {
896  *  vendorID      [0] Unsigned,
897  *  serviceNumber [1] Unsigned,
898  *  resultBlock   [2] ABSTRACT-SYNTAX.&Type OPTIONAL
899  * }
900  * @param tvb the tv buffer of the current data
901  * @param pinfo the packet info of the current data
902  * @param tree the tree to append this item to
903  * @param offset the offset in the tvb
904  * @return modified offset
905  */
906 static guint
907 fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
908
909 /**
910  * ConfirmedTextMessage-Request ::=  SEQUENCE {
911  *  textMessageSourceDevice [0] BACnetObjectIdentifier,
912  *  messageClass            [1] CHOICE {
913  *      numeric   [0] Unsigned,
914  *      character [1] CharacterString
915  *      } OPTIONAL,
916  *  messagePriority         [2] ENUMERATED {
917  *      normal (0),
918  *      urgent (1)
919  *      },
920  *  message [3] CharacterString
921  * }
922  * @param tvb the tv buffer of the current data
923  * @param pinfo the packet info of the current data
924  * @param tree the tree to append this item to
925  * @param offset the offset in the tvb
926  * @return modified offset
927  */
928 static guint
929 fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
930
931 /**
932  * ReinitializeDevice-Request ::= SEQUENCE {
933  *  reinitializedStateOfDevice  [0] ENUMERATED {
934  *      coldstart    (0),
935  *      warmstart    (1),
936  *      startbackup  (2),
937  *      endbackup    (3),
938  *      startrestore (4),
939  *      endrestore   (5),
940  *      abortrestor  (6)
941  *      },
942  *  password                    [1] CharacterString (SIZE(1..20)) OPTIONAL
943  * }
944  * @param tvb the tv buffer of the current data
945  * @param pinfo the packet info of the current data
946  * @param tree the tree to append this item to
947  * @param offset the offset in the tvb
948  * @return modified offset
949  */
950 static guint
951 fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
952
953 /**
954  * VTOpen-Request ::= SEQUENCE {
955  *  vtClass BACnetVTClass,
956  *  localVTSessionIdentifier    Unsigned8
957  * }
958  * @param tvb the tv buffer of the current data
959  * @param pinfo the packet info of the current data
960  * @param tree the tree to append this item to
961  * @param offset the offset in the tvb
962  * @return modified offset
963  */
964 static guint
965 fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
966
967 /**
968  * VTOpen-ACK ::= SEQUENCE {
969  *  remoteVTSessionIdentifier   Unsigned8
970  * }
971  * @param tvb the tv buffer of the current data
972  * @param pinfo the packet info of the current data
973  * @param tree the tree to append this item to
974  * @param offset the offset in the tvb
975  * @return modified offset
976  */
977 static guint
978 fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
979
980 /**
981  * VTClose-Request ::= SEQUENCE {
982  *  listOfRemoteVTSessionIdentifiers    SEQUENCE OF Unsigned8
983  * }
984  * @param tvb the tv buffer of the current data
985  * @param pinfo the packet info of the current data
986  * @param tree the tree to append this item to
987  * @param offset the offset in the tvb
988  * @return modified offset
989  */
990 static guint
991 fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
992
993 /**
994  * VTData-Request ::= SEQUENCE {
995  *  vtSessionIdentifier Unsigned8,
996  *  vtNewData           OCTET STRING,
997  *  vtDataFlag          Unsigned (0..1)
998  * }
999  * @param tvb the tv buffer of the current data
1000  * @param pinfo the packet info of the current data
1001  * @param tree the tree to append this item to
1002  * @param offset the offset in the tvb
1003  * @return modified offset
1004  */
1005 static guint
1006 fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1007
1008 /**
1009  * VTData-ACK ::= SEQUENCE {
1010  *  allNewDataAccepted  [0] BOOLEAN,
1011  *  acceptedOctetCount  [1] Unsigned OPTIONAL -- present only if allNewDataAccepted = FALSE
1012  * }
1013  * @param tvb the tv buffer of the current data
1014  * @param pinfo the packet info of the current data
1015  * @param tree the tree to append this item to
1016  * @param offset the offset in the tvb
1017  * @return modified offset
1018  */
1019 static guint
1020 fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1021
1022 /**
1023  * Authenticate-Request ::= SEQUENCE {
1024  *  pseudoRandomNumber     [0] Unsigned32,
1025  *  excpectedInvokeID      [1] Unsigned8 OPTIONAL,
1026  *  operatorName           [2] CharacterString OPTIONAL,
1027  *  operatorPassword       [3] CharacterString (SIZE(1..20)) OPTIONAL,
1028  *  startEncypheredSession [4] BOOLEAN OPTIONAL
1029  * }
1030  * @param tvb the tv buffer of the current data
1031  * @param pinfo the packet info of the current data
1032  * @param tree the tree to append this item to
1033  * @param offset the offset in the tvb
1034  * @return modified offset
1035  */
1036 static guint
1037 fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1038
1039 /**
1040  * Authenticate-ACK ::= SEQUENCE {
1041  *  modifiedRandomNumber    Unsigned32,
1042  * }
1043  * @param tvb the tv buffer of the current data
1044  * @param pinfo the packet info of the current data
1045  * @param tree the tree to append this item to
1046  * @param offset the offset in the tvb
1047  * @return modified offset
1048  */
1049 static guint
1050 fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1051
1052 /**
1053  * RequestKey-Request ::= SEQUENCE {
1054  *  requestingDeviceIdentifier BACnetObjectIdentifier,
1055  *  requestingDeviceAddress    BACnetAddress,
1056  *  remoteDeviceIdentifier     BACnetObjectIdentifier,
1057  *  remoteDeviceAddress        BACnetAddress
1058  * }
1059  * @param tvb the tv buffer of the current data
1060  * @param pinfo the packet info of the current data
1061  * @param tree the tree to append this item to
1062  * @param offset the offset in the tvb
1063  * @return modified offset
1064  */
1065 static guint
1066 fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1067
1068 /**
1069  * Unconfirmed-Service-Request ::= CHOICE {
1070  * }
1071  * @param tvb the tv buffer of the current data
1072  * @param pinfo the packet info of the current data
1073  * @param tree the tree to append this item to
1074  * @param offset the offset in the tvb
1075  * @param service_choice the service choice
1076  * @return modified offset
1077  */
1078 static guint
1079 fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
1080
1081 /**
1082  * UnconfirmedCOVNotification-Request ::= SEQUENCE {
1083  *  subscriberProcessIdentifier [0] Unsigned32,
1084  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
1085  *  monitoredObjectIdentifier   [2] BACnetObjectIdentifer,
1086  *  timeRemaining               [3] unsigned,
1087  *  listOfValues                [4] SEQUENCE OF BACnetPropertyValues
1088  * }
1089  * @param tvb the tv buffer of the current data
1090  * @param pinfo the packet info of the current data
1091  * @param tree the tree to append this item to
1092  * @param offset the offset in the tvb
1093  * @return modified offset
1094  */
1095 static guint
1096 fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1097
1098 /**
1099  * UnconfirmedEventNotification-Request ::= SEQUENCE {
1100  *  ProcessIdentifier           [0] Unsigned32,
1101  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
1102  *  eventObjectIdentifier       [2] BACnetObjectIdentifer,
1103  *  timeStamp                   [3] BACnetTimeStamp,
1104  *  notificationClass           [4] unsigned,
1105  *  priority                    [5] unsigned8,
1106  *  eventType                   [6] BACnetEventType,
1107  *  messageText                 [7] CharacterString OPTIONAL,
1108  *  notifyType                  [8] BACnetNotifyType,
1109  *  ackRequired                 [9] BOOLEAN OPTIONAL,
1110  *  fromState                  [10] BACnetEventState OPTIONAL,
1111  *  toState                    [11] BACnetEventState,
1112  *  eventValues                [12] BACnetNotificationParameters OPTIONAL
1113  * }
1114  * @param tvb the tv buffer of the current data
1115  * @param pinfo the packet info of the current data
1116  * @param tree the tree to append this item to
1117  * @param offset the offset in the tvb
1118  * @return modified offset
1119  */
1120 static guint
1121 fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1122
1123 /**
1124  * I-Am-Request ::= SEQUENCE {
1125  *  aAmDeviceIdentifier BACnetObjectIdentifier,
1126  *  maxAPDULengthAccepted   Unsigned,
1127  *  segmentationSupported   BACnetSegmentation,
1128  *  vendorID    Unsigned
1129  * }
1130  * @param tvb the tv buffer of the current data
1131  * @param pinfo the packet info of the current data
1132  * @param tree the tree to append this item to
1133  * @param offset the offset in the tvb
1134  * @return modified offset
1135  */
1136 static guint
1137 fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1138
1139
1140 /**
1141  * I-Have-Request ::= SEQUENCE {
1142  *  deviceIdentifier  BACnetObjectIdentifier,
1143  *  objectIdentifier  BACnetObjectIdentifier,
1144  *  objectName        CharacterString
1145  * }
1146  * @param tvb the tv buffer of the current data
1147  * @param pinfo the packet info of the current data
1148  * @param tree the tree to append this item to
1149  * @param offset the offset in the tvb
1150  * @return modified offset
1151  */
1152 static guint
1153 fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1154
1155 /**
1156  * UnconfirmedPrivateTransfer-Request ::= SEQUENCE {
1157  *  vendorID          [0] Unsigned,
1158  *  serviceNumber     [1] Unsigned,
1159  *  serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
1160  * }
1161  * @param tvb the tv buffer of the current data
1162  * @param pinfo the packet info of the current data
1163  * @param tree the tree to append this item to
1164  * @param offset the offset in the tvb
1165  * @return modified offset
1166  */
1167 static guint
1168 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1169
1170 /**
1171  * UnconfirmedTextMessage-Request ::=  SEQUENCE {
1172  *  textMessageSourceDevice [0] BACnetObjectIdentifier,
1173  *  messageClass            [1] CHOICE {
1174  *      numeric   [0] Unsigned,
1175  *      character [1] CharacterString
1176  *      } OPTIONAL,
1177  *  messagePriority         [2] ENUMERATED {
1178  *      normal (0),
1179  *      urgent (1)
1180  *      },
1181  *  message                 [3] CharacterString
1182  * }
1183  * @param tvb the tv buffer of the current data
1184  * @param pinfo the packet info of the current data
1185  * @param tree the tree to append this item to
1186  * @param offset the offset in the tvb
1187  * @return modified offset
1188  */
1189 static guint
1190 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1191
1192 /**
1193  * TimeSynchronization-Request ::=  SEQUENCE {
1194  *  BACnetDateTime
1195  * }
1196  * @param tvb the tv buffer of the current data
1197  * @param pinfo the packet info of the current data
1198  * @param tree the tree to append this item to
1199  * @param offset the offset in the tvb
1200  * @return modified offset
1201  */
1202 static guint
1203 fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1204
1205 /**
1206  * UTCTimeSynchronization-Request ::=  SEQUENCE {
1207  *  BACnetDateTime
1208  * }
1209  * @param tvb the tv buffer of the current data
1210  * @param pinfo the packet info of the current data
1211  * @param tree the tree to append this item to
1212  * @param offset the offset in the tvb
1213  * @return modified offset
1214  */
1215 static guint
1216 fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1217
1218 /**
1219  * Who-Has-Request ::=  SEQUENCE {
1220  *  limits SEQUENCE {
1221  *      deviceInstanceRangeLowLimit  [0] Unsigned (0..4194303),
1222  *      deviceInstanceRangeHighLimit [1] Unsigned (0..4194303)
1223  *      } OPTIONAL,
1224  *  object CHOICE {
1225  *      objectIdentifier             [2] BACnetObjectIdentifier,
1226  *      objectName                   [3] CharacterString
1227  *      }
1228  * }
1229  * @param tvb the tv buffer of the current data
1230  * @param pinfo the packet info of the current data
1231  * @param tree the tree to append this item to
1232  * @param offset the offset in the tvb
1233  * @return modified offset
1234  */
1235 static guint
1236 fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1237
1238 /**
1239  * Who-Is-Request ::= SEQUENCE {
1240  *  deviceInstanceRangeLowLimit  [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1241  *  deviceInstanceRangeHighLimit [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1242  * }
1243  * @param tvb the tv buffer of the current data
1244  * @param tree the tree to append this item to
1245  * @param offset the offset in the tvb
1246  * @return modified offset
1247  */
1248 static guint
1249 fWhoIsRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1250
1251 /**
1252  * BACnet-Error ::= CHOICE {
1253  *  addListElement           [8] ChangeList-Error,
1254  *  removeListElement        [9] ChangeList-Error,
1255  *  writePropertyMultiple   [16] WritePropertyMultiple-Error,
1256  *  confirmedPrivatTransfer [18] ConfirmedPrivateTransfer-Error,
1257  *  vtClose                 [22] VTClose-Error,
1258  *  readRange               [26] ObjectAccessService-Error
1259  *                          [default] Error
1260  * }
1261  * @param tvb the tv buffer of the current data
1262  * @param pinfo the packet info of the current data
1263  * @param tree the tree to append this item to
1264  * @param offset the offset in the tvb
1265  * @param service the service
1266  * @return modified offset
1267  */
1268 static guint
1269 fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service);
1270
1271 /**
1272  * Dissect a BACnetError in a context tag
1273  *
1274  * @param tvb the tv buffer of the current data
1275  * @param pinfo the packet info of the current data
1276  * @param tree the tree to append this item to
1277  * @param offset the offset in the tvb
1278  * @return modified offset
1279  */
1280 static guint fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1281
1282 /**
1283  * ChangeList-Error ::= SEQUENCE {
1284  *    errorType                [0] Error,
1285  *    firstFailedElementNumber [1] Unsigned
1286  *    }
1287  * }
1288  * @param tvb the tv buffer of the current data
1289  * @param pinfo the packet info of the current data
1290  * @param tree the tree to append this item to
1291  * @param offset the offset in the tvb
1292  * @return modified offset
1293  */
1294 static guint
1295 fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1296
1297 /**
1298  * CreateObject-Error ::= SEQUENCE {
1299  *    errorType                [0] Error,
1300  *    firstFailedElementNumber [1] Unsigned
1301  *    }
1302  * }
1303  * @param tvb the tv buffer of the current data
1304  * @param pinfo the packet info of the current data
1305  * @param tree the tree to append this item to
1306  * @param offset the offset in the tvb
1307  * @return modified offset
1308  */
1309 static guint
1310 fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1311
1312 /**
1313  * ConfirmedPrivateTransfer-Error ::= SEQUENCE {
1314  *    errorType       [0] Error,
1315  *    vendorID        [1] Unsigned,
1316  *    serviceNumber   [2] Unsigned,
1317  *    errorParameters [3] ABSTRACT-SYNTAX.&Type OPTIONAL
1318  *    }
1319  * }
1320  * @param tvb the tv buffer of the current data
1321  * @param pinfo the packet info of the current data
1322  * @param tree the tree to append this item to
1323  * @param offset the offset in the tvb
1324  * @return modified offset
1325  */
1326 static guint
1327 fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1328
1329 /**
1330  * WritePropertyMultiple-Error ::= SEQUENCE {
1331  *    errorType               [0] Error,
1332  *    firstFailedWriteAttempt [1] Unsigned
1333  *    }
1334  * }
1335  * @param tvb the tv buffer of the current data
1336  * @param pinfo the packet info of the current data
1337  * @param tree the tree to append this item to
1338  * @param offset the offset in the tvb
1339  * @return modified offset
1340  */
1341 static guint
1342 fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1343
1344 /**
1345  * VTClose-Error ::= SEQUENCE {
1346  *    errorType                  [0] Error,
1347  *    listOfVTSessionIdentifiers [1] SEQUENCE OF Unsigned8 OPTIONAL
1348  *    }
1349  * }
1350  * @param tvb the tv buffer of the current data
1351  * @param pinfo the packet info of the current data
1352  * @param tree the tree to append this item to
1353  * @param offset the offset in the tvb
1354  * @return modified offset
1355  */
1356 static guint
1357 fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1358
1359 /**
1360  * BACnet Application Types chapter 20.2.1
1361  * @param tvb the tv buffer of the current data
1362  * @param pinfo the packet info of the current data
1363  * @param tree the tree to append this item to
1364  * @param offset the offset in the tvb
1365  * @param label the label of this item
1366  * @return modified offset
1367  */
1368 static guint
1369 fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
1370
1371 /**
1372  * BACnetActionCommand ::= SEQUENCE {
1373  *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1374  *  objectIdentifier    [1] BACnetObjectIdentifier,
1375  *  propertyIdentifier  [2] BACnetPropertyIdentifier,
1376  *  propertyArrayIndex  [3] Unsigned OPTIONAL, -- used only with array datatype
1377  *  propertyValue       [4] ABSTRACT-SYNTAX.&Type,
1378  *  priority            [5] Unsigned (1..16) OPTIONAL, -- used only when property is commandable
1379  *  postDelay           [6] Unsigned OPTIONAL,
1380  *  quitOnFailure       [7] BOOLEAN,
1381  *  writeSuccessful     [8] BOOLEAN
1382  * }
1383  * @param tvb the tv buffer of the current data
1384  * @param pinfo the packet info of the current data
1385  * @param tree the tree to append this item to
1386  * @param offset the offset in the tvb
1387  * @param tag_match the tag number
1388  * @return modified offset
1389  */
1390 static guint
1391 fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match);
1392
1393 /**
1394  * BACnetActionList ::= SEQUENCE {
1395  *  action  [0] SEQUENCE of BACnetActionCommand
1396  * }
1397  * @param tvb the tv buffer of the current data
1398  * @param pinfo the packet info of the current data
1399  * @param tree the tree to append this item to
1400  * @param offset the offset in the tvb
1401  * @return modified offset
1402  */
1403 static guint
1404 fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1405
1406 /** BACnetAddress ::= SEQUENCE {
1407  *  network-number  Unsigned16, -- A value 0 indicates the local network
1408  *  mac-address     OCTET STRING -- A string of length 0 indicates a broadcast
1409  * }
1410  * @param tvb the tv buffer of the current data
1411  * @param pinfo the packet info of the current data
1412  * @param tree the tree to append this item to
1413  * @param offset the offset in the tvb
1414  * @return modified offset
1415  */
1416 static guint
1417 fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1418
1419 /**
1420  * BACnetAddressBinding ::= SEQUENCE {
1421  *  deviceObjectID  BACnetObjectIdentifier
1422  *  deviceAddress   BacnetAddress
1423  * }
1424  * @param tvb the tv buffer of the current data
1425  * @param pinfo the packet info of the current data
1426  * @param tree the tree to append this item to
1427  * @param offset the offset in the tvb
1428  * @return modified offset
1429  */
1430 static guint
1431 fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1432
1433 /**
1434  * BACnetCalendarEntry ::= CHOICE {
1435  *  date        [0] Date,
1436  *  dateRange   [1] BACnetDateRange,
1437  *  weekNDay    [2] BacnetWeekNday
1438  * }
1439  * @param tvb the tv buffer of the current data
1440  * @param pinfo the packet info of the current data
1441  * @param tree the tree to append this item to
1442  * @param offset the offset in the tvb
1443  * @return modified offset
1444  */
1445 static guint
1446 fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1447
1448 /**
1449  * BACnetClientCOV ::= CHOICE {
1450  *  real-increment  REAL,
1451  *  default-increment   NULL
1452  * }
1453  * @param tvb the tv buffer of the current data
1454  * @param tree the tree to append this item to
1455  * @param offset the offset in the tvb
1456  * @return modified offset
1457  */
1458 static guint
1459 fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1460
1461
1462 /**
1463  * BACnetDailySchedule ::= SEQUENCE {
1464  *  day-schedule    [0] SENQUENCE OF BACnetTimeValue
1465  * }
1466  * @param tvb the tv buffer of the current data
1467  * @param pinfo the packet info of the current data
1468  * @param tree the tree to append this item to
1469  * @param offset the offset in the tvb
1470  * @return modified offset
1471  */
1472 static guint
1473 fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1474
1475 /**
1476  * BACnetWeeklySchedule ::= SEQUENCE {
1477  *  week-schedule    SENQUENCE SIZE (7) OF BACnetDailySchedule
1478  * }
1479  * @param tvb the tv buffer of the current data
1480  * @param pinfo the packet info of the current data
1481  * @param tree the tree to append this item to
1482  * @param offset the offset in the tvb
1483  * @return modified offset
1484  */
1485 static guint
1486 fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1487
1488 /**
1489  * BACnetDateRange ::= SEQUENCE {
1490  *  StartDate   Date,
1491  *  EndDate     Date
1492  * }
1493  * @param tvb the tv buffer of the current data
1494  * @param pinfo the packet info of the current data
1495  * @param tree the tree to append this item to
1496  * @param offset the offset in the tvb
1497  * @return modified offset
1498  */
1499 static guint
1500 fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1501
1502 /**
1503  * BACnetDateTime ::= SEQUENCE {
1504  *  date   Date,
1505  *  time   Time
1506  * }
1507  * @param tvb the tv buffer of the current data
1508  * @param pinfo the packet info of the current data
1509  * @param tree the tree to append this item to
1510  * @param offset the offset in the tvb
1511  * @param label the label of this item
1512  * @return modified offset
1513  */
1514 static guint
1515 fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
1516
1517 /**
1518  * BACnetDestination ::= SEQUENCE {
1519  *  validDays   BACnetDaysOfWeek,
1520  *  fromTime    Time,
1521  *  toTime      Time,
1522  *  recipient   BACnetRecipient,
1523  *  processIdentifier   Unsigned32,
1524  *  issueConfirmedNotifications BOOLEAN,
1525  *  transitions BACnetEventTransitionBits
1526  * }
1527  * @param tvb the tv buffer of the current data
1528  * @param pinfo the packet info of the current data
1529  * @param tree the tree to append this item to
1530  * @param offset the offset in the tvb
1531  * @return modified offset
1532  */
1533 static guint
1534 fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1535
1536 /**
1537  * BACnetDeviceObjectPropertyReference ::= SEQUENCE {
1538  *  objectIdentifier    [0] BACnetObjectIdentifier,
1539  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1540  *  propertyArrayIndex  [2] Unsigend OPTIONAL,
1541  *  deviceIdentifier    [3] BACnetObjectIdentifier OPTIONAL
1542  * }
1543  * @param tvb the tv buffer of the current data
1544  * @param pinfo the packet info of the current data
1545  * @param tree the tree to append this item to
1546  * @param offset the offset in the tvb
1547  * @return modified offset
1548  */
1549 static guint
1550 fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1551
1552 /**
1553  * BACnetObjectPropertyReference ::= SEQUENCE {
1554  *  objectIdentifier    [0] BACnetObjectIdentifier,
1555  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1556  *  propertyArrayIndex  [2] Unsigend OPTIONAL,
1557  * }
1558  * @param tvb the tv buffer of the current data
1559  * @param pinfo the packet info of the current data
1560  * @param tree the tree to append this item to
1561  * @param offset the offset in the tvb
1562  * @return modified offset
1563  */
1564 static guint
1565 fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1566
1567 /**
1568  * BACnetDeviceObjectReference ::= SEQUENCE {
1569  *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1570  *  objectIdentifier    [1] BACnetObjectIdentifier
1571  * }
1572  * @param tvb the tv buffer of the current data
1573  * @param pinfo the packet info of the current data
1574  * @param tree the tree to append this item to
1575  * @param offset the offset in the tvb
1576  * @return modified offset
1577  */
1578 static guint
1579 fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1580
1581 /**
1582  * BACnetEventParameter ::= CHOICE {
1583  *  change-of-bitstring             [0] SEQUENCE {
1584  *      time-delay                       [0] Unsigned,
1585  *      bitmask                          [1] BIT STRING,
1586  *      list-of-bitstring-values         [2] SEQUENCE OF BIT STRING
1587  *      },
1588  *  change-of-state                 [1] SEQUENCE {
1589  *      time-delay     [0] Unsigned,
1590  *      list-of-values [1] SEQUENCE OF BACnetPropertyStates
1591  *      },
1592  *  change-of-value                 [2] SEQUENCE {
1593  *      time-delay   [0] Unsigned,
1594  *      cov-criteria [1] CHOICE {
1595  *          bitmask                       [0] BIT STRING,
1596  *          referenced-property-increment [1] REAL
1597  *          }
1598  *      },
1599  *  command-failure                 [3] SEQUENCE {
1600  *      time-delay                       [0] Unsigned,
1601  *      feedback-property-reference      [1] BACnetDeviceObjectPropertyReference
1602  *      },
1603  *  floating-limit                  [4] SEQUENCE {
1604  *      time-delay                       [0] Unsigned,
1605  *      setpoint-reference               [1] BACnetDeviceObjectPropertyReference,
1606  *      low-diff-limit                   [2] REAL,
1607  *      high-diff-limit                  [3] REAL,
1608  *      deadband                         [4] REAL
1609  *      },
1610  *  out-of-range                    [5] SEQUENCE {
1611  *      time-delay                       [0] Unsigned,
1612  *      low-limit                        [1] REAL,
1613  *      high-limit                       [2] REAL,
1614  *      deadband                         [3] REAL
1615  *      },
1616  *  -- context tag 7 is deprecated
1617  *  change-of-life-safety           [8] SEQUENCE {
1618  *      time-delay                       [0] Unsigned,
1619  *      list-of-life-safety-alarm-values [1] SEQUENCE OF BACnetLifeSafetyState,
1620  *      list-of-alarm-values             [2] SEQUENCE OF BACnetLifeSafetyState,
1621  *      mode-property-reference          [3] BACnetDeviceObjectPropertyReference
1622  *      },
1623  *  extended                        [9] SEQUENCE {
1624  *      vendor-id                        [0] Unsigned16,
1625  *      extended-event-type              [1] Unsigned,
1626  *      parameters                       [2] SEQUENCE OF CHOICE {
1627  *          null        NULL,
1628  *          real        REAL,
1629  *          integer     Unsigned,
1630  *          boolean     BOOLEAN,
1631  *          double      Double,
1632  *          octet       OCTET STRING,
1633  *          bitstring   BIT STRING,
1634  *          enum        ENUMERATED,
1635  *          reference   [0] BACnetDeviceObjectPropertyReference
1636  *          }
1637  *      },
1638  *  buffer-ready                    [10] SEQUENCE {
1639  *      notification-threshold           [0] Unsigned,
1640  *      previous-notification-count      [1] Unsigned32
1641  *      },
1642  * unsigned-range                   [11] SEQUENCE {
1643  *      time-delay                       [0] Unsigned,
1644  *      low-limit                        [1] Unsigned,
1645  *      high-limit                       [2] Unsigned,
1646  *      }
1647  * -- context tag 12 is reserved for future addenda
1648  * access-event                     [13] SEQUENCE {
1649  *      list-of-access-events            [0] SEQUENCE OF BACnetAccessEvent,
1650  *      access-event-time-reference      [1] BACnetDeviceObjectPropertyReference
1651  *      }
1652  * double-out-of-range              [14] SEQUENCE {
1653  *      time-delay                       [0] Unsigned,
1654  *      low-limit                        [1] Double,
1655  *      high-limit                       [2] Double,
1656  *      deadband                         [3] Double
1657  *  }
1658  *  signed-out-of-range             [15] SEQUENCE {
1659  *      time-delay                       [0] Unsigned,
1660  *      low-limit                        [1] INTEGER,
1661  *      high-limit                       [2] INTEGER,
1662  *      deadband                         [3] Unsigned
1663  *  }
1664  *  unsigned-out-of-range           [16] SEQUENCE {
1665  *      time-delay                       [0] Unsigned,
1666  *      low-limit                        [1] Unsigned,
1667  *      high-limit                       [2] Unsigned,
1668  *      deadband                         [3] Unsigned
1669  *   }
1670  *  change-of-characterstring       [17] SEQUENCE {
1671  *      time-delay                       [0] Unsigned,
1672  *      list-of-alarm-values             [1] SEQUENCE OF CharacterString,
1673  *   }
1674  *  change-of-status-flags          [18] SEQUENCE {
1675  *      time-delay                       [0] Unsigned,
1676  *      selected-flags                   [1] BACnetStatusFlags
1677  *   }
1678  * }
1679  * @param tvb the tv buffer of the current data
1680  * @param tree the tree to append this item to
1681  * @param offset the offset in the tvb
1682  * @return modified offset
1683  */
1684 static guint
1685 fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1686
1687
1688
1689 /**
1690  * BACnetLogRecord ::= SEQUENCE {
1691  *  timestamp   [0] BACnetDateTime,
1692  *  logDatum    [1] CHOICE {
1693  *      log-status      [0] BACnetLogStatus,
1694  *      boolean-value   [1] BOOLEAN,
1695  *      real-value      [2] REAL,
1696  *      enum-value      [3] ENUMERATED, -- Optionally limited to 32 bits
1697  *      unsigned-value  [4] Unsigned, -- Optionally limited to 32 bits
1698  *      signed-value    [5] INTEGER, -- Optionally limited to 32 bits
1699  *      bitstring-value [6] BIT STRING, -- Optionally limited to 32 bits
1700  *      null-value      [7] NULL,
1701  *      failure         [8] Error,
1702  *      time-change     [9] REAL,
1703  *      any-value       [10] ABSTRACT-SYNTAX.&Type -- Optional
1704  *      }
1705  *  statusFlags [2] BACnetStatusFlags OPTIONAL
1706  * }
1707  * @param tvb the tv buffer of the current data
1708  * @param pinfo the packet info of the current data
1709  * @param tree the tree to append this item to
1710  * @param offset the offset in the tvb
1711  * @return modified offset
1712  */
1713 static guint
1714 fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1715
1716 /**
1717  * BACnetEventLogRecord ::= SEQUENCE {
1718  *  timestamp [0] BACnetDateTime,
1719  *  logDatum  [1] CHOICE {
1720  *      log-status   [0] BACnetLogStatus,
1721  *      notification [1] ConfirmedEventNotification-Request,
1722  *      time-change  [2] REAL,
1723  *      }
1724  * }
1725  * @param tvb the tv buffer of the current data
1726  * @param pinfo the packet info of the current data
1727  * @param tree the tree to append this item to
1728  * @param offset the offset in the tvb
1729  * @return modified offset
1730  */
1731 static guint
1732 fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1733
1734 static guint
1735 fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1736
1737 /**
1738  * BACnetNotificationParameters ::= CHOICE {
1739  *  change-of-bitstring [0] SEQUENCE {
1740  *      referenced-bitstring [0] BIT STRING,
1741  *      status-flags         [1] BACnetStatusFlags
1742  *      },
1743  *  change-of-state [1] SEQUENCE {
1744  *      new-state            [0] BACnetPropertyStatus,
1745  *      status-flags         [1] BACnetStatusFlags
1746  *      },
1747  *  change-of-value [2] SEQUENCE {
1748  *      new-value            [0] CHOICE {
1749  *          changed-bits        [0] BIT STRING,
1750  *          changed-value       [1] REAL
1751  *          },
1752  *      status-flags         [1] BACnetStatusFlags
1753  *      },
1754  *  command-failure [3] SEQUENCE {
1755  *      command-value        [0] ABSTRACT-SYNTAX.&Type, -- depends on ref property
1756  *      status-flags         [1] BACnetStatusFlags
1757  *      feedback-value       [2] ABSTRACT-SYNTAX.&Type -- depends on ref property
1758  *      },
1759  *  floating-limit [4]  SEQUENCE {
1760  *      reference-value      [0] REAL,
1761  *      status-flags         [1] BACnetStatusFlags
1762  *      setpoint-value       [2] REAL,
1763  *      error-limit          [3] REAL
1764  *      },
1765  *  out-of-range [5]    SEQUENCE {
1766  *      exceeding-value      [0] REAL,
1767  *      status-flags         [1] BACnetStatusFlags
1768  *      deadband             [2] REAL,
1769  *      exceeded-limit       [3] REAL
1770  *      },
1771  *  complex-event-type  [6] SEQUENCE OF BACnetPropertyValue,
1772  * -- complex tag 7 is deprecated
1773  *  change-of-life-safety [8]   SEQUENCE {
1774  *      new-state            [0] BACnetLifeSafetyState,
1775  *      new-mode             [1] BACnetLifeSafetyState
1776  *      status-flags         [2] BACnetStatusFlags,
1777  *      operation-expected   [3] BACnetLifeSafetyOperation
1778  *      },
1779  *  extended [9]   SEQUENCE {
1780  *      vendor-id            [0] Unsigned16,
1781  *      extended-event-type  [1] Unsigned,
1782  *      parameters           [2] SEQUENCE OF CHOICE {
1783  *          null                NULL,
1784  *          real                REAL,
1785  *          integer             Unsigned,
1786  *          boolean             BOOLEAN,
1787  *          double              Double,
1788  *          octet               OCTET STRING,
1789  *          bitstring           BIT STRING,
1790  *          enum                ENUMERATED,
1791  *          propertyValue       [0] BACnetDeviceObjectPropertyValue
1792  *          }
1793  *      },
1794  *  buffer-ready [10]    SEQUENCE {
1795  *      buffer-property      [0] BACnetDeviceObjectPropertyReference,
1796  *      previous-notification[1] Unsigned32,
1797  *      current-notification [2] BACneUnsigned32tDateTime
1798  *      },
1799  *  unsigned-range [11]    SEQUENCE {
1800  *      exceeding-value      [0] Unsigned,
1801  *      status-flags         [1] BACnetStatusFlags,
1802  *      exceeded-limit       [2] Unsigned
1803  *      },
1804  * -- context tag 12 is reserved for future addenda
1805  *  access-event [13]    SEQUENCE {
1806  *      access-event          [0] BACnetAccessEvent,
1807  *      status-flags          [1] BACnetStatusFlags,
1808  *      access-event-tag      [2] Unsigned,
1809  *      access-event-time     [3] BACnetTimeStamp,
1810  *      access-credential     [4] BACnetDeviceObjectReference,
1811  *      authentication-factor [5] BACnetAuthenticationFactor OPTIONAL
1812  *      },
1813  *  double-out-of-range [14]    SEQUENCE {
1814  *      exceeding-value      [0] Double,
1815  *      status-flags         [1] BACnetStatusFlags
1816  *      deadband             [2] Double,
1817  *      exceeded-limit       [3] Double
1818  *      },
1819  *  signed-out-of-range [15]    SEQUENCE {
1820  *      exceeding-value      [0] INTEGER,
1821  *      status-flags         [1] BACnetStatusFlags
1822  *      deadband             [2] Unsigned,
1823  *      exceeded-limit       [3] INTEGER
1824  *      },
1825  *  unsigned-out-of-range [16]    SEQUENCE {
1826  *      exceeding-value      [0] Unsigned,
1827  *      status-flags         [1] BACnetStatusFlags
1828  *      deadband             [2] Unsigned,
1829  *      exceeded-limit       [3] Unsigned
1830  *      },
1831  *  change-of-characterstring [17]    SEQUENCE {
1832  *      changed-value        [0] CharacterString,
1833  *      status-flags         [1] BACnetStatusFlags
1834  *      alarm-value          [2] CharacterString
1835  *      },
1836  *  change-of-status-flags [18]    SEQUENCE {
1837  *      present-value        [0] ABSTRACT-SYNTAX.&Type OPTIONAL,
1838  *                              -- depends on referenced property
1839  *      referenced-flags     [1] BACnetStatusFlags
1840  *      },
1841  * }
1842  * @param tvb the tv buffer of the current data
1843  * @param pinfo the packet info of the current data
1844  * @param tree the tree to append this item to
1845  * @param offset the offset in the tvb
1846  * @return modified offset
1847  */
1848 static guint
1849 fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1850
1851 /**
1852  * BACnetObjectPropertyReference ::= SEQUENCE {
1853  *  objectIdentifier    [0] BACnetObjectIdentifier,
1854  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1855  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
1856  * }
1857  * @param tvb the tv buffer of the current data
1858  * @param pinfo the packet info of the current data
1859  * @param tree the tree to append this item to
1860  * @param offset the offset in the tvb
1861  * @return modified offset
1862  */
1863 static guint
1864 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1865
1866 #if 0
1867 /**
1868  * BACnetObjectPropertyValue ::= SEQUENCE {
1869  *      objectIdentifier   [0] BACnetObjectIdentifier,
1870  *      propertyIdentifier [1] BACnetPropertyIdentifier,
1871  *      propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
1872  *                                                -- if omitted with an array the entire array is referenced
1873  *      value              [3] ABSTRACT-SYNTAX.&Type, --any datatype appropriate for the specified property
1874  *      priority           [4] Unsigned (1..16) OPTIONAL
1875  * }
1876  * @param tvb the tv buffer of the current data
1877  * @param tree the tree to append this item to
1878  * @param offset the offset in the tvb
1879  * @return modified offset
1880  */
1881 static guint
1882 fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, guint offset);
1883 #endif
1884
1885 /**
1886  * BACnetPriorityArray ::= SEQUENCE SIZE (16) OF BACnetPriorityValue
1887  * @param tvb the tv buffer of the current data
1888  * @param pinfo the packet info of the current data
1889  * @param tree the tree to append this item to
1890  * @param offset the offset in the tvb
1891  * @return modified offset
1892  */
1893 static guint
1894 fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1895
1896 static guint
1897 fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list);
1898
1899 /**
1900  * BACnetPropertyReference ::= SEQUENCE {
1901  *  propertyIdentifier  [0] BACnetPropertyIdentifier,
1902  *  propertyArrayIndex  [1] Unsigned OPTIONAL, -- used only with array datatype
1903  * }
1904  * @param tvb the tv buffer of the current data
1905  * @param pinfo the packet info of the current data
1906  * @param tree the tree to append this item to
1907  * @param offset the offset in the tvb
1908  * @return modified offset
1909  */
1910 static guint
1911 fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list);
1912
1913 /* static guint
1914 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset); */
1915
1916 static guint
1917 fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1918
1919 static guint
1920 fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1921
1922 /**
1923  * BACnetPropertyValue ::= SEQUENCE {
1924  *      PropertyIdentifier [0] BACnetPropertyIdentifier,
1925  *      propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatypes
1926  *                                                -- if omitted with an array the entire array is referenced
1927  *      value              [2] ABSTRACT-SYNTAX.&Type, -- any datatype appropriate for the specified property
1928  *      priority           [3] Unsigned (1..16) OPTIONAL -- used only when property is commandable
1929  * }
1930  * @param tvb the tv buffer of the current data
1931  * @param pinfo the packet info of the current data
1932  * @param tree the tree to append this item to
1933  * @param offset the offset in the tvb
1934  * @return modified offset
1935  */
1936 static guint
1937 fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1938
1939 static guint
1940 fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset);
1941
1942 /**
1943  * BACnet Application PDUs chapter 21
1944  * BACnetRecipient::= CHOICE {
1945  *  device  [0] BACnetObjectIdentifier
1946  *  address [1] BACnetAddress
1947  * }
1948  * @param tvb the tv buffer of the current data
1949  * @param pinfo the packet info of the current data
1950  * @param tree the tree to append this item to
1951  * @param offset the offset in the tvb
1952  * @return modified offset
1953  */
1954 static guint
1955 fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1956
1957 /**
1958  * BACnet Application PDUs chapter 21
1959  * BACnetRecipientProcess::= SEQUENCE {
1960  *  recipient   [0] BACnetRecipient
1961  *  processID   [1] Unsigned32
1962  * }
1963  * @param tvb the tv buffer of the current data
1964  * @param pinfo the packet info of the current data
1965  * @param tree the tree to append this item to
1966  * @param offset the offset in the tvb
1967  * @return modified offset
1968  */
1969 static guint
1970 fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1971
1972 static guint
1973 fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1974
1975 #if 0
1976 /**
1977  * BACnetSessionKey ::= SEQUENCE {
1978  *  sessionKey  OCTET STRING (SIZE(8)), -- 56 bits for key, 8 bits for checksum
1979  *  peerAddress BACnetAddress
1980  * }
1981  * @param tvb the tv buffer of the current data
1982  * @param tree the tree to append this item to
1983  * @param offset the offset in the tvb
1984  * @return modified offset
1985  * @todo check if checksum is displayed correctly
1986  */
1987 static guint
1988 fSessionKey(tvbuff_t *tvb, proto_tree *tree, guint offset);
1989 #endif
1990
1991 /**
1992  * BACnetSpecialEvent ::= SEQUENCE {
1993  *  period      CHOICE {
1994  *      calendarEntry       [0] BACnetCalendarEntry,
1995  *      calendarRefernce    [1] BACnetObjectIdentifier
1996  *      },
1997  *      listOfTimeValues    [2] SEQUENCE OF BACnetTimeValue,
1998  *      eventPriority       [3] Unsigned (1..16)
1999  * }
2000  * @param tvb the tv buffer of the current data
2001  * @param pinfo the packet info of the current data
2002  * @param tree the tree to append this item to
2003  * @param offset the offset in the tvb
2004  * @return modified offset
2005  */
2006 static guint
2007 fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2008
2009 /**
2010  * BACnetTimeStamp ::= CHOICE {
2011  *  time            [0] Time,
2012  *  sequenceNumber  [1] Unsigned (0..65535),
2013  *  dateTime        [2] BACnetDateTime
2014  * }
2015  * @param tvb the tv buffer of the current data
2016  * @param pinfo the packet info of the current data
2017  * @param tree the tree to append this item to
2018  * @param offset the offset in the tvb
2019  * @param label the label of this item
2020  * @return modified offset
2021  */
2022 static guint
2023 fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2024
2025 static guint
2026 fEventTimeStamps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2027
2028 /**
2029  * BACnetTimeValue ::= SEQUENCE {
2030  *  time    Time,
2031  *  value   ABSTRACT-SYNTAX.&Type -- any primitive datatype, complex types cannot be decoded
2032  * }
2033  * @param tvb the tv buffer of the current data
2034  * @param pinfo the packet info of the current data
2035  * @param tree the tree to append this item to
2036  * @param offset the offset in the tvb
2037  * @return modified offset
2038  */
2039 static guint
2040 fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2041
2042 #if 0
2043 /**
2044  * BACnetVTSession ::= SEQUENCE {
2045  *  local-vtSessionID   Unsigned8,
2046  *  remote-vtSessionID  Unsigned8,
2047  *  remote-vtAddress    BACnetAddress
2048  * }
2049  * @param tvb the tv buffer of the current data
2050  * @param tree the tree to append this item to
2051  * @param offset the offset in the tvb
2052  * @return modified offset
2053  */
2054 static guint
2055 fVTSession(tvbuff_t *tvb, proto_tree *tree, guint offset);
2056 #endif
2057
2058 /**
2059  * BACnetWeekNDay ::= OCTET STRING (SIZE (3))
2060  * -- first octet month (1..12) January = 1, X'FF' = any month
2061  * -- second octet weekOfMonth where: 1 = days numbered 1-7
2062  * -- 2 = days numbered 8-14
2063  * -- 3 = days numbered 15-21
2064  * -- 4 = days numbered 22-28
2065  * -- 5 = days numbered 29-31
2066  * -- 6 = last 7 days of this month
2067  * -- X'FF' = any week of this month
2068  * -- third octet dayOfWeek (1..7) where 1 = Monday
2069  * -- 7 = Sunday
2070  * -- X'FF' = any day of week
2071  * @param tvb the tv buffer of the current data
2072  * @param pinfo the packet info of the current data
2073  * @param tree the tree to append this item to
2074  * @param offset the offset in the tvb
2075  * @return modified offset
2076  */
2077 static guint
2078 fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2079
2080 /**
2081  * ReadAccessResult ::= SEQUENCE {
2082  *  objectIdentifier            [0] BACnetObjectIdentifier,
2083  *  listOfResults               [1] SEQUENCE OF SEQUENCE {
2084  *      propertyIdentifier      [2] BACnetPropertyIdentifier,
2085  *      propertyArrayIndex      [3] Unsigned OPTIONAL, -- used only with array datatype if omitted with an array the entire array is referenced
2086  *      readResult  CHOICE {
2087  *          propertyValue       [4] ABSTRACT-SYNTAX.&Type,
2088  *          propertyAccessError [5] Error
2089  *      }
2090  *  } OPTIONAL
2091  * }
2092  * @param tvb the tv buffer of the current data
2093  * @param pinfo the packet info of the current data
2094  * @param tree the tree to append this item to
2095  * @param offset the offset in the tvb
2096  * @return modified offset
2097  */
2098 static guint
2099 fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2100
2101 /**
2102  * ReadAccessSpecification ::= SEQUENCE {
2103  *  objectIdentifier         [0] BACnetObjectIdentifier,
2104  *  listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference
2105  * }
2106  * @param tvb the tv buffer of the current data
2107  * @param pinfo the packet info of the current data
2108  * @param subtree the subtree to append this item to
2109  * @param offset the offset in the tvb
2110  * @return modified offset
2111  */
2112 static guint
2113 fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2114
2115 /**
2116  * WriteAccessSpecification ::= SEQUENCE {
2117  *  objectIdentifier [0] BACnetObjectIdentifier,
2118  *  listOfProperty   [1] SEQUENCE OF BACnetPropertyValue
2119  * }
2120  * @param tvb the tv buffer of the current data
2121  * @param pinfo the packet info of the current data
2122  * @param subtree the sub tree to append this item to
2123  * @param offset the offset in the tvb
2124  * @return modified offset
2125  */
2126 static guint
2127 fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2128
2129
2130 /********************************************************* Helper functions *******************************************/
2131
2132 /**
2133  * extracts the tag number from the tag header.
2134  * @param tvb the tv buffer of the current data "TestyVirtualBuffer"
2135  * @param offset the offset in the tvb in actual tvb
2136  * @return Tag Number corresponding to BACnet 20.2.1.2 Tag Number
2137  */
2138 static guint
2139 fTagNo(tvbuff_t *tvb, guint offset);
2140
2141 /**
2142  * splits Tag Header coresponding to 20.2.1 General Rules For BACnet Tags
2143  * @param tvb the tv buffer of the current data = "TestyVirtualBuffer"
2144  * @param pinfo the packet info of the current data = packet info
2145  * @param offset the offset in the tvb = offset in actual tvb
2146  * @return tag_no BACnet 20.2.1.2 Tag Number
2147  * @return class_tag BACnet 20.2.1.1 Class
2148  * @return lvt BACnet 20.2.1.3 Length/Value/Type
2149  * @return offs = length of this header
2150  */
2151
2152 static guint
2153 fTagHeader(tvbuff_t *tvb, packet_info *pinfo, guint offset, guint8 *tag_no, guint8* class_tag, guint32 *lvt);
2154
2155
2156 /**
2157  * adds processID with max 32Bit unsigned Integer Value to tree
2158  * @param tvb the tv buffer of the current data
2159  * @param pinfo the packet info of the current data
2160  * @param tree the tree to append this item to
2161  * @param offset the offset in the tvb
2162  * @return modified offset
2163  */
2164 static guint
2165 fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2166
2167 /**
2168  * adds timeSpan with max 32Bit unsigned Integer Value to tree
2169  * @param tvb the tv buffer of the current data
2170  * @param pinfo the packet info of the current data
2171  * @param tree the tree to append this item to
2172  * @param offset the offset in the tvb
2173  * @return modified offset
2174  */
2175 static guint
2176 fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2177
2178 /**
2179  * BACnet Application PDUs chapter 21
2180  * BACnetPropertyIdentifier::= ENUMERATED {
2181  *   @see bacapp_property_identifier
2182  * }
2183  * @param tvb the tv buffer of the current data
2184  * @param pinfo the packet info of the current data
2185  * @param tree the tree to append this item to
2186  * @param offset the offset in the tvb
2187  * @return modified offset
2188  */
2189 static guint
2190 fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2191
2192 /**
2193  * BACnet Application PDUs chapter 21
2194  * BACnetPropertyArrayIndex::= ENUMERATED {
2195  *   @see bacapp_property_array_index
2196  * }
2197  * @param tvb the tv buffer of the current data
2198  * @param pinfo the packet info of the current data
2199  * @param tree the tree to append this item to
2200  * @param offset the offset in the tvb
2201  * @return modified offset
2202  */
2203 static guint
2204 fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2205
2206 /**
2207  * listOfEventSummaries ::= SEQUENCE OF SEQUENCE {
2208  *  objectIdentifier        [0] BACnetObjectIdentifier,
2209  *  eventState              [1] BACnetEventState,
2210  *  acknowledgedTransitions [2] BACnetEventTransitionBits,
2211  *  eventTimeStamps         [3] SEQURNCE SIZE (3) OF BACnetTimeStamps,
2212  *  notifyType              [4] BACnetNotifyType,
2213  *  eventEnable             [5] BACnetEventTransitionBits,
2214  *  eventPriorities         [6] SEQUENCE SIZE (3) OF Unsigned
2215  * }
2216  * @param tvb the tv buffer of the current data
2217  * @param pinfo the packet info of the current data
2218  * @param tree the tree to append this item to
2219  * @param offset the offset in the tvb
2220  * @return modified offset
2221  */
2222 static guint
2223 flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2224
2225 /**
2226  * SelectionCriteria ::= SEQUENCE {
2227  *  propertyIdentifier [0] BACnetPropertyIdentifier,
2228  *  propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatype
2229  *  relationSpecifier  [2] ENUMERATED { bacapp_relationSpecifier },
2230  *  comparisonValue    [3] ABSTRACT-SYNTAX.&Type
2231  * }
2232  * @param tvb the tv buffer of the current data
2233  * @param pinfo the packet info of the current data
2234  * @param tree the tree to append this item to
2235  * @param offset the offset in the tvb
2236  * @return modified offset
2237  */
2238 static guint
2239 fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2240
2241 /**
2242  * objectSelectionCriteria ::= SEQUENCE {
2243  *  selectionLogic          [0] ENUMERATED { bacapp_selectionLogic },
2244  *  listOfSelectionCriteria [1] SelectionCriteria
2245  * }
2246  * @param tvb the tv buffer of the current data
2247  * @param pinfo the packet info of the current data
2248  * @param subtree the sub tree to append this item to
2249  * @param offset the offset in the tvb
2250  * @return modified offset
2251  */
2252 static guint
2253 fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2254
2255 /**
2256  * BACnet-Error ::= SEQUENCE {
2257  *    error-class ENUMERATED {},
2258  *    error-code  ENUMERATED {}
2259  *    }
2260  * }
2261  * @param tvb the tv buffer of the current data
2262  * @param pinfo the packet info of the current data
2263  * @param tree the tree to append this item to
2264  * @param offset the offset in the tvb
2265  * @return modified offset
2266  */
2267 static guint
2268 fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2269
2270 /**
2271  * Generic handler for context tagged values.  Mostly for handling
2272  * vendor-defined properties and services.
2273  * @param tvb the tv buffer of the current data
2274  * @param pinfo the packet info of the current data
2275  * @param tree the tree to append this item to
2276  * @param offset the offset in the tvb
2277  * @return modified offset
2278  * @todo beautify this ugly construct
2279  */
2280 static guint
2281 fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2282
2283 /**
2284  * realizes some ABSTRACT-SYNTAX.&Type
2285  * @param tvb the tv buffer of the current data
2286  * @param pinfo the packet info of the current data
2287  * @param tree the tree to append this item to
2288  * @param offset the offset in the tvb
2289  * @return modified offset
2290  * @todo beautify this ugly construct
2291  */
2292 static guint
2293 fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2294
2295
2296 static guint
2297 fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label,
2298     const value_string *src);
2299
2300 /**
2301  * register_bacapp
2302  */
2303 void
2304 proto_register_bacapp(void);
2305
2306 /**
2307  * proto_reg_handoff_bacapp
2308  */
2309 void
2310 proto_reg_handoff_bacapp(void);
2311
2312 /**
2313  * converts XXX coded strings to UTF-8
2314  * else 'in' is copied to 'out'
2315  * @param in  -- pointer to string
2316  * @param inbytesleft size of int bytes
2317  * @param out -- pointer to string
2318  * @param outbytesleft size of out bytes
2319  * @param fromcoding coding type
2320  * @return count of modified characters of returned string, -1 for errors
2321  */
2322 static guint32
2323 fConvertXXXtoUTF8(gchar *in, gsize *inbytesleft, gchar *out, gsize *outbytesleft, const gchar *fromcoding);
2324
2325 static void
2326 uni_to_string(char * data, gsize str_length, char *dest_buf);
2327
2328 /* <<<< formerly bacapp.h */
2329
2330 /* reassembly table for segmented messages */
2331 static reassembly_table msg_reassembly_table;
2332
2333 /* some necessary forward function prototypes */
2334 static guint
2335 fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
2336     const gchar *label, const value_string *vs);
2337
2338 static const char *bacapp_unknown_service_str = "unknown service";  /* Usage: no format specifiers */
2339 static const char *ASHRAE_Reserved_Fmt = "(%d) Reserved for Use by ASHRAE";
2340 static const char *Vendor_Proprietary_Fmt = "(%d) Vendor Proprietary Value";
2341
2342 static const value_string
2343 BACnetTypeName[] = {
2344     { 0, "Confirmed-REQ"},
2345     { 1, "Unconfirmed-REQ"},
2346     { 2, "Simple-ACK"},
2347     { 3, "Complex-ACK"},
2348     { 4, "Segment-ACK"},
2349     { 5, "Error"},
2350     { 6, "Reject"},
2351     { 7, "Abort"},
2352     { 0, NULL }
2353 };
2354
2355 static const true_false_string segments_follow = {
2356     "Segmented Request",
2357     "Unsegmented Request"
2358 };
2359
2360 static const true_false_string more_follow = {
2361     "More Segments Follow",
2362     "No More Segments Follow"
2363 };
2364
2365 static const true_false_string segmented_accept = {
2366     "Segmented Response accepted",
2367     "Segmented Response not accepted"
2368 };
2369
2370 static const true_false_string
2371 BACnetTagClass = {
2372     "Context Specific Tag",
2373     "Application Tag"
2374 };
2375
2376 static const value_string
2377 BACnetMaxSegmentsAccepted [] = {
2378     { 0,  "Unspecified"},
2379     { 1,  "2 segments"},
2380     { 2,  "4 segments"},
2381     { 3,  "8 segments"},
2382     { 4, "16 segments"},
2383     { 5, "32 segments"},
2384     { 6, "64 segments"},
2385     { 7, "Greater than 64 segments"},
2386     { 0, NULL }
2387 };
2388
2389 static const value_string
2390 BACnetMaxAPDULengthAccepted [] = {
2391     {  0, "Up to MinimumMessageSize (50 octets)"},
2392     {  1, "Up to 128 octets"},
2393     {  2, "Up to 206 octets (fits in a LonTalk frame)"},
2394     {  3, "Up to 480 octets (fits in an ARCNET frame)"},
2395     {  4, "Up to 1024 octets"},
2396     {  5, "Up to 1476 octets (fits in an ISO 8802-3 frame)"},
2397     {  6, "reserved by ASHRAE"},
2398     {  7, "reserved by ASHRAE"},
2399     {  8, "reserved by ASHRAE"},
2400     {  9, "reserved by ASHRAE"},
2401     { 10, "reserved by ASHRAE"},
2402     { 11, "reserved by ASHRAE"},
2403     { 12, "reserved by ASHRAE"},
2404     { 13, "reserved by ASHRAE"},
2405     { 14, "reserved by ASHRAE"},
2406     { 15, "reserved by ASHRAE"},
2407     { 0, NULL}
2408 };
2409
2410 static const value_string
2411 BACnetRejectReason [] = {
2412     {0, "other"},
2413     {1, "buffer-overflow"},
2414     {2, "inconsistent-parameters"},
2415     {3, "invalid-parameter-data-type"},
2416     {4, "invalid-tag"},
2417     {5, "missing-required-parameter"},
2418     {6, "parameter-out-of-range"},
2419     {7, "too-many-arguments"},
2420     {8, "undefined-enumeration"},
2421     {9, "unrecognized-service"},
2422     {0, NULL}
2423 };
2424
2425 static const value_string
2426 BACnetRestartReason [] = {
2427     { 0, "unknown"},
2428     { 1, "coldstart"},
2429     { 2, "warmstart"},
2430     { 3, "detected-power-lost"},
2431     { 4, "detected-powered-off"},
2432     { 5, "hardware-watchdog"},
2433     { 6, "software-watchdog"},
2434     { 7, "suspended"},
2435     { 0, NULL}
2436 };
2437
2438 static const value_string
2439 BACnetApplicationTagNumber [] = {
2440     {  0, "Null"},
2441     {  1, "Boolean"},
2442     {  2, "Unsigned Integer"},
2443     {  3, "Signed Integer (2's complement notation)"},
2444     {  4, "Real (ANSI/IEE-754 floating point)"},
2445     {  5, "Double (ANSI/IEE-754 double precision floating point)"},
2446     {  6, "Octet String"},
2447     {  7, "Character String"},
2448     {  8, "Bit String"},
2449     {  9, "Enumerated"},
2450     { 10, "Date"},
2451     { 11, "Time"},
2452     { 12, "BACnetObjectIdentifier"},
2453     { 13, "reserved by ASHRAE"},
2454     { 14, "reserved by ASHRAE"},
2455     { 15, "reserved by ASHRAE"},
2456     { 0,  NULL}
2457 };
2458
2459 static const value_string
2460 BACnetAction [] = {
2461     { 0, "direct"},
2462     { 1, "reverse"},
2463     { 0, NULL}
2464 };
2465
2466 static const value_string
2467 BACnetAccessEvent [] = {
2468     {  0, "none"},
2469     {  1, "granted"},
2470     {  2, "muster"},
2471     {  3, "passback-detected"},
2472     {  4, "duress"},
2473     {  5, "trace"},
2474     {  6, "lockout-max-attempts"},
2475     {  7, "lockout-other"},
2476     {  8, "lockout-relinquished"},
2477     {  9, "lockout-by-higher-priority"},
2478     { 10, "out-of-service"},
2479     { 11, "out-of-service-relinquished"},
2480     { 12, "accompaniment-by"},
2481     { 13, "authentication-factor-read"},
2482     { 14, "authorization-delayed"},
2483     { 15, "verification-required"},
2484     /* Enumerated values 128-511 are used for events
2485      * which indicate that access has been denied. */
2486     { 128, "denied-deny-all"},
2487     { 129, "denied-unknown-credential"},
2488     { 130, "denied-authentication-unavailable"},
2489     { 131, "denied-authentication-factor-timeout"},
2490     { 132, "denied-incorrect-authentication-factor"},
2491     { 133, "denied-zone-no-access-rights"},
2492     { 134, "denied-point-no-access-rights"},
2493     { 135, "denied-no-access-rights"},
2494     { 136, "denied-out-of-time-range"},
2495     { 137, "denied-threat-level"},
2496     { 138, "denied-passback"},
2497     { 139, "denied-unexpected-location-usage"},
2498     { 140, "denied-max-attempts"},
2499     { 141, "denied-lower-occupancy-limit"},
2500     { 142, "denied-upper-occupancy-limit"},
2501     { 143, "denied-authentication-factor-lost"},
2502     { 144, "denied-authentication-factor-stolen"},
2503     { 145, "denied-authentication-factor-damaged"},
2504     { 146, "denied-authentication-factor-destroyed"},
2505     { 147, "denied-authentication-factor-disabled"},
2506     { 148, "denied-authentication-factor-error"},
2507     { 149, "denied-credential-unassigned"},
2508     { 150, "denied-credential-not-provisioned"},
2509     { 151, "denied-credential-not-yet-active"},
2510     { 152, "denied-credential-expired"},
2511     { 153, "denied-credential-manual-disable"},
2512     { 154, "denied-credential-lockout"},
2513     { 155, "denied-credential-max-days"},
2514     { 156, "denied-credential-max-uses"},
2515     { 157, "denied-credential-inactivity"},
2516     { 158, "denied-credential-disabled"},
2517     { 159, "denied-no-accompaniment"},
2518     { 160, "denied-incorrect-accompaniment"},
2519     { 161, "denied-lockout"},
2520     { 162, "denied-verification-failed"},
2521     { 163, "denied-verification-timeout"},
2522     { 164, "denied-other"},
2523     { 0,  NULL}
2524 /* Enumerated values 0-512 are reserved for definition by ASHRAE.
2525    Enumerated values 512-65535 may be used by others subject to
2526    procedures and constraints described in Clause 23. */
2527 };
2528
2529 static const value_string
2530 BACnetFileAccessMethod [] = {
2531     { 0, "record-access"},
2532     { 1, "stream-access"},
2533     { 0, NULL}
2534 };
2535
2536 /* For some reason, BACnet defines the choice parameter
2537    in the file read and write services backwards from the
2538    BACnetFileAccessMethod enumeration.
2539 */
2540 static const value_string
2541 BACnetFileAccessOption [] = {
2542     { 0, "stream access"},
2543     { 1, "record access"},
2544     { 0, NULL}
2545 };
2546
2547 static const value_string
2548 BACnetFileStartOption [] = {
2549     { 0, "File Start Position: "},
2550     { 1, "File Start Record: "},
2551     { 0, NULL}
2552 };
2553
2554 static const value_string
2555 BACnetFileRequestCount [] = {
2556     { 0, "Requested Octet Count: "},
2557     { 1, "Requested Record Count: "},
2558     { 0, NULL}
2559 };
2560
2561 static const value_string
2562 BACnetFileWriteInfo [] = {
2563     { 0, "File Data: "},
2564     { 1, "Record Count: "},
2565     { 0, NULL}
2566 };
2567
2568 static const value_string
2569 BACnetAbortReason [] = {
2570     { 0, "other"},
2571     { 1, "buffer-overflow"},
2572     { 2, "invalid-apdu-in-this-state"},
2573     { 3, "preempted-by-higher-priority-task"},
2574     { 4, "segmentation-not-supported"},
2575     { 0, NULL}
2576 };
2577
2578 static const value_string
2579 BACnetLifeSafetyMode [] = {
2580     {  0, "off"},
2581     {  1, "on"},
2582     {  2, "test"},
2583     {  3, "manned"},
2584     {  4, "unmanned"},
2585     {  5, "armed"},
2586     {  6, "disarmed"},
2587     {  7, "prearmed"},
2588     {  8, "slow"},
2589     {  9, "fast"},
2590     { 10, "disconnected"},
2591     { 11, "enabled"},
2592     { 12, "disabled"},
2593     { 13, "atomic-release-disabled"},
2594     { 14, "default"},
2595     { 0,  NULL}
2596 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2597    Enumerated values 256-65535 may be used by others subject to
2598    procedures and constraints described in Clause 23. */
2599 };
2600
2601 static const value_string
2602 BACnetLifeSafetyOperation [] = {
2603     { 0, "none"},
2604     { 1, "silence"},
2605     { 2, "silence-audible"},
2606     { 3, "silence-visual"},
2607     { 4, "reset"},
2608     { 5, "reset-alarm"},
2609     { 6, "reset-fault"},
2610     { 7, "unsilence"},
2611     { 8, "unsilence-audible"},
2612     { 9, "unsilence-visual"},
2613     { 0, NULL}
2614 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
2615    Enumerated values 64-65535 may be used by others subject to
2616    procedures and constraints described in Clause 23. */
2617 };
2618
2619 static const value_string
2620 BACnetLimitEnable [] = {
2621     { 0, "lowLimitEnable"},
2622     { 1, "highLimitEnable"},
2623     { 0, NULL}
2624 };
2625
2626 static const value_string
2627 BACnetLifeSafetyState [] = {
2628     {  0, "quiet"},
2629     {  1, "pre-alarm"},
2630     {  2, "alarm"},
2631     {  3, "fault"},
2632     {  4, "fault-pre-alarm"},
2633     {  5, "fault-alarm"},
2634     {  6, "not-ready"},
2635     {  7, "active"},
2636     {  8, "tamper"},
2637     {  9, "test-alarm"},
2638     { 10, "test-active"},
2639     { 11, "test-fault"},
2640     { 12, "test-fault-alarm"},
2641     { 13, "holdup"},
2642     { 14, "duress"},
2643     { 15, "tamper-alarm"},
2644     { 16, "abnormal"},
2645     { 17, "emergency-power"},
2646     { 18, "delayed"},
2647     { 19, "blocked"},
2648     { 20, "local-alarm"},
2649     { 21, "general-alarm"},
2650     { 22, "supervisory"},
2651     { 23, "test-supervisory"},
2652     { 0,  NULL}
2653 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2654    Enumerated values 256-65535 may be used by others subject to
2655    procedures and constraints described in Clause 23. */
2656 };
2657
2658 static const value_string
2659 BACnetConfirmedServiceChoice [] = {
2660     {  0, "acknowledgeAlarm"},
2661     {  1, "confirmedCOVNotification"},
2662     {  2, "confirmedEventNotification"},
2663     {  3, "getAlarmSummary"},
2664     {  4, "getEnrollmentSummary"},
2665     {  5, "subscribeCOV"},
2666     {  6, "atomicReadFile"},
2667     {  7, "atomicWriteFile"},
2668     {  8, "addListElement"},
2669     {  9, "removeListElement"},
2670     { 10, "createObject"},
2671     { 11, "deleteObject"},
2672     { 12, "readProperty"},
2673     { 13, "readPropertyConditional"},
2674     { 14, "readPropertyMultiple"},
2675     { 15, "writeProperty"},
2676     { 16, "writePropertyMultiple"},
2677     { 17, "deviceCommunicationControl"},
2678     { 18, "confirmedPrivateTransfer"},
2679     { 19, "confirmedTextMessage"},
2680     { 20, "reinitializeDevice"},
2681     { 21, "vtOpen"},
2682     { 22, "vtClose"},
2683     { 23, "vtData"},
2684     { 24, "authenticate"},
2685     { 25, "requestKey"},
2686     { 26, "readRange"},
2687     { 27, "lifeSafetyOperation"},
2688     { 28, "subscribeCOVProperty"},
2689     { 29, "getEventInformation"},
2690     { 30, "reserved by ASHRAE"},
2691     { 0,  NULL}
2692 };
2693
2694 static const value_string
2695 BACnetReliability [] = {
2696     {  0, "no-fault-detected"},
2697     {  1, "no-sensor"},
2698     {  2, "over-range"},
2699     {  3, "under-range"},
2700     {  4, "open-loop"},
2701     {  5, "shorted-loop"},
2702     {  6, "no-output"},
2703     {  7, "unreliable-other"},
2704     {  8, "process-error"},
2705     {  9, "multi-state-fault"},
2706     { 10, "configuration-error"},
2707     /* enumeration value 11 is reserved for a future addendum */
2708     { 12, "communication-failure"},
2709     { 13, "member-fault"},
2710     { 0,  NULL}
2711 };
2712
2713 static const value_string
2714 BACnetUnconfirmedServiceChoice [] = {
2715     { 0, "i-Am"},
2716     { 1, "i-Have"},
2717     { 2, "unconfirmedCOVNotification"},
2718     { 3, "unconfirmedEventNotification"},
2719     { 4, "unconfirmedPrivateTransfer"},
2720     { 5, "unconfirmedTextMessage"},
2721     { 6, "timeSynchronization"},
2722     { 7, "who-Has"},
2723     { 8, "who-Is"},
2724     { 9, "utcTimeSynchronization"},
2725     { 0, NULL}
2726 };
2727
2728 static const value_string
2729 BACnetUnconfirmedServiceRequest [] = {
2730     { 0, "i-Am-Request"},
2731     { 1, "i-Have-Request"},
2732     { 2, "unconfirmedCOVNotification-Request"},
2733     { 3, "unconfirmedEventNotification-Request"},
2734     { 4, "unconfirmedPrivateTransfer-Request"},
2735     { 5, "unconfirmedTextMessage-Request"},
2736     { 6, "timeSynchronization-Request"},
2737     { 7, "who-Has-Request"},
2738     { 8, "who-Is-Request"},
2739     { 9, "utcTimeSynchonization-Request"},
2740     { 0, NULL}
2741 };
2742
2743 static const value_string
2744 BACnetObjectType [] = {
2745     {  0, "analog-input"},
2746     {  1, "analog-output"},
2747     {  2, "analog-value"},
2748     {  3, "binary-input"},
2749     {  4, "binary-output"},
2750     {  5, "binary-value"},
2751     {  6, "calendar"},
2752     {  7, "command"},
2753     {  8, "device"},
2754     {  9, "event-enrollment"},
2755     { 10, "file"},
2756     { 11, "group"},
2757     { 12, "loop"},
2758     { 13, "multi-state-input"},
2759     { 14, "multi-state-output"},
2760     { 15, "notification-class"},
2761     { 16, "program"},
2762     { 17, "schedule"},
2763     { 18, "averaging"},
2764     { 19, "multi-state-value"},
2765     { 20, "trend-log"},
2766     { 21, "life-safety-point"},
2767     { 22, "life-safety-zone"},
2768     { 23, "accumulator"},
2769     { 24, "pulse-converter"},
2770     { 25, "event-log"},
2771     { 26, "global-group"},
2772     { 27, "trend-log-multiple"},
2773     { 28, "load-control"},
2774     { 29, "structured-view"},
2775     { 30, "access-door"},     /* 30-37 added with addanda 135-2008j */
2776     /* value 31 is unassigned */
2777     { 32, "access-credential"},
2778     { 33, "access-point"},
2779     { 34, "access-rights"},
2780     { 35, "access-user"},
2781     { 36, "access-zone"},
2782     { 37, "credential-data-input"},
2783     { 38, "network-security"},
2784     { 39, "bitstring-value"},     /* 39-50 added with addenda 135-2008w */
2785     { 40, "characterstring-value"},
2786     { 41, "date-pattern-value"},
2787     { 42, "date-value"},
2788     { 43, "datetime-pattern-value"},
2789     { 44, "datetime-value"},
2790     { 45, "integer-value"},
2791     { 46, "large-analog-value"},
2792     { 47, "octetstring-value"},
2793     { 48, "positive-integer-value"},
2794     { 49, "time-pattern-value"},
2795     { 50, "time-value"},
2796     { 0,  NULL}
2797 /* Enumerated values 0-127 are reserved for definition by ASHRAE.
2798    Enumerated values 128-1023 may be used by others subject to
2799    the procedures and constraints described in Clause 23. */
2800 };
2801
2802 static const value_string
2803 BACnetEngineeringUnits [] = {
2804     {   0, "Sq Meters"},
2805     {   1, "Sq Feet"},
2806     {   2, "Milliamperes"},
2807     {   3, "Amperes"},
2808     {   4, "Ohms"},
2809     {   5, "Volts"},
2810     {   6, "Kilovolts"},
2811     {   7, "Megavolts"},
2812     {   8, "Volt Amperes"},
2813     {   9, "Kilovolt Amperes"},
2814     {  10, "Megavolt Amperes"},
2815     {  11, "Volt Amperes Reactive"},
2816     {  12, "Kilovolt Amperes Reactive"},
2817     {  13, "Megavolt Amperes Reactive"},
2818     {  14, "Degrees Phase"},
2819     {  15, "Power Factor"},
2820     {  16, "Joules"},
2821     {  17, "Kilojoules"},
2822     {  18, "Watt Hours"},
2823     {  19, "Kilowatt Hours"},
2824     {  20, "BTUs"},
2825     {  21, "Therms"},
2826     {  22, "Ton Hours"},
2827     {  23, "Joules Per Kg Dry Air"},
2828     {  24, "BTUs Per Pound Dry Air"},
2829     {  25, "Cycles Per Hour"},
2830     {  26, "Cycles Per Minute"},
2831     {  27, "Hertz"},
2832     {  28, "Grams Of Water Per Kilogram Dry Air"},
2833     {  29, "Relative Humidity"},
2834     {  30, "Millimeters"},
2835     {  31, "Meters"},
2836     {  32, "Inches"},
2837     {  33, "Feed"},
2838     {  34, "Watts Per Sq Foot"},
2839     {  35, "Watts Per Sq meter"},
2840     {  36, "Lumens"},
2841     {  37, "Lux"},
2842     {  38, "Foot Candles"},
2843     {  39, "Kilograms"},
2844     {  40, "Pounds Mass"},
2845     {  41, "Tons"},
2846     {  42, "Kgs per Second"},
2847     {  43, "Kgs Per Minute"},
2848     {  44, "Kgs Per Hour"},
2849     {  45, "Pounds Mass Per Minute"},
2850     {  46, "Pounds Mass Per Hour"},
2851     {  47, "Watt"},
2852     {  48, "Kilowatts"},
2853     {  49, "Megawatts"},
2854     {  50, "BTUs Per Hour"},
2855     {  51, "Horsepower"},
2856     {  52, "Tons Refrigeration"},
2857     {  53, "Pascals"},
2858     {  54, "Kilopascals"},
2859     {  55, "Bars"},
2860     {  56, "Pounds Force Per Square Inch"},
2861     {  57, "Centimeters Of Water"},
2862     {  58, "Inches Of Water"},
2863     {  59, "Millimeters Of Mercury"},
2864     {  60, "Centimeters Of Mercury"},
2865     {  61, "Inches Of Mercury"},
2866     {  62, "Degrees Celsius"},
2867     {  63, "Degrees Kelvin"},
2868     {  64, "Degrees Fahrenheit"},
2869     {  65, "Degree Days Celsius"},
2870     {  66, "Degree Days Fahrenheit"},
2871     {  67, "Years"},
2872     {  68, "Months"},
2873     {  69, "Weeks"},
2874     {  70, "Days"},
2875     {  71, "Hours"},
2876     {  72, "Minutes"},
2877     {  73, "Seconds"},
2878     {  74, "Meters Per Second"},
2879     {  75, "Kilometers Per Hour"},
2880     {  76, "Feed Per Second"},
2881     {  77, "Feet Per Minute"},
2882     {  78, "Miles Per Hour"},
2883     {  79, "Cubic Feet"},
2884     {  80, "Cubic Meters"},
2885     {  81, "Imperial Gallons"},
2886     {  82, "Liters"},
2887     {  83, "US Gallons"},
2888     {  84, "Cubic Feet Per Minute"},
2889     {  85, "Cubic Meters Per Second"},
2890     {  86, "Imperial Gallons Per Minute"},
2891     {  87, "Liters Per Second"},
2892     {  88, "Liters Per Minute"},
2893     {  89, "US Gallons Per Minute"},
2894     {  90, "Degrees Angular"},
2895     {  91, "Degrees Celsius Per Hour"},
2896     {  92, "Degrees Celsius Per Minute"},
2897     {  93, "Degrees Fahrenheit Per Hour"},
2898     {  94, "Degrees Fahrenheit Per Minute"},
2899     {  95, "No Units"},
2900     {  96, "Parts Per Million"},
2901     {  97, "Parts Per Billion"},
2902     {  98, "Percent"},
2903     {  99, "Pecent Per Second"},
2904     { 100, "Per Minute"},
2905     { 101, "Per Second"},
2906     { 102, "Psi Per Degree Fahrenheit"},
2907     { 103, "Radians"},
2908     { 104, "Revolutions Per Min"},
2909     { 105, "Currency1"},
2910     { 106, "Currency2"},
2911     { 107, "Currency3"},
2912     { 108, "Currency4"},
2913     { 109, "Currency5"},
2914     { 110, "Currency6"},
2915     { 111, "Currency7"},
2916     { 112, "Currency8"},
2917     { 113, "Currency9"},
2918     { 114, "Currency10"},
2919     { 115, "Sq Inches"},
2920     { 116, "Sq Centimeters"},
2921     { 117, "BTUs Per Pound"},
2922     { 118, "Centimeters"},
2923     { 119, "Pounds Mass Per Second"},
2924     { 120, "Delta Degrees Fahrenheit"},
2925     { 121, "Delta Degrees Kelvin"},
2926     { 122, "Kilohms"},
2927     { 123, "Megohms"},
2928     { 124, "Millivolts"},
2929     { 125, "Kilojoules Per Kg"},
2930     { 126, "Megajoules"},
2931     { 127, "Joules Per Degree Kelvin"},
2932     { 128, "Joules Per Kg Degree Kelvin"},
2933     { 129, "Kilohertz"},
2934     { 130, "Megahertz"},
2935     { 131, "Per Hour"},
2936     { 132, "Milliwatts"},
2937     { 133, "Hectopascals"},
2938     { 134, "Millibars"},
2939     { 135, "Cubic Meters Per Hour"},
2940     { 136, "Liters Per Hour"},
2941     { 137, "KWatt Hours Per Square Meter"},
2942     { 138, "KWatt Hours Per Square Foot"},
2943     { 139, "Megajoules Per Square Meter"},
2944     { 140, "Megajoules Per Square Foot"},
2945     { 141, "Watts Per Sq Meter Degree Kelvin"},
2946     { 142, "Cubic Feet Per Second"},
2947     { 143, "Percent Obstruction Per Foot"},
2948     { 144, "Percent Obstruction Per Meter"},
2949     { 145, "milliohms"},
2950     { 146, "megawatt-hours"},
2951     { 147, "kilo-btus"},
2952     { 148, "mega-btus"},
2953     { 149, "kilojoules-per-kilogram-dry-air"},
2954     { 150, "megajoules-per-kilogram-dry-air"},
2955     { 151, "kilojoules-per-degree-Kelvin"},
2956     { 152, "megajoules-per-degree-Kelvin"},
2957     { 153, "newton"},
2958     { 154, "grams-per-second"},
2959     { 155, "grams-per-minute"},
2960     { 156, "tons-per-hour"},
2961     { 157, "kilo-btus-per-hour"},
2962     { 158, "hundredths-seconds"},
2963     { 159, "milliseconds"},
2964     { 160, "newton-meters"},
2965     { 161, "millimeters-per-second"},
2966     { 162, "millimeters-per-minute"},
2967     { 163, "meters-per-minute"},
2968     { 164, "meters-per-hour"},
2969     { 165, "cubic-meters-per-minute"},
2970     { 166, "meters-per-second-per-second"},
2971     { 167, "amperes-per-meter"},
2972     { 168, "amperes-per-square-meter"},
2973     { 169, "ampere-square-meters"},
2974     { 170, "farads"},
2975     { 171, "henrys"},
2976     { 172, "ohm-meters"},
2977     { 173, "siemens"},
2978     { 174, "siemens-per-meter"},
2979     { 175, "teslas"},
2980     { 176, "volts-per-degree-Kelvin"},
2981     { 177, "volts-per-meter"},
2982     { 178, "webers"},
2983     { 179, "candelas"},
2984     { 180, "candelas-per-square-meter"},
2985     { 181, "degrees-Kelvin-per-hour"},
2986     { 182, "degrees-Kelvin-per-minute"},
2987     { 183, "joule-seconds"},
2988     { 184, "radians-per-second"},
2989     { 185, "square-meters-per-Newton"},
2990     { 186, "kilograms-per-cubic-meter"},
2991     { 187, "newton-seconds"},
2992     { 188, "newtons-per-meter"},
2993     { 189, "watts-per-meter-per-degree-Kelvin"},
2994     { 190, "micro-siemens"},
2995     { 191, "cubic-feet-per-hour"},
2996     { 192, "us-gallons-per-hour"},
2997     { 193, "kilometers"},
2998     { 194, "micrometers"},
2999     { 195, "grams"},
3000     { 196, "milligrams"},
3001     { 197, "milliliters"},
3002     { 198, "milliliters-per-second"},
3003     { 199, "decibels"},
3004     { 200, "decibels-millivolt"},
3005     { 201, "decibels-volt"},
3006     { 202, "millisiemens"},
3007     { 203, "watt-hours-reactive"},
3008     { 204, "kilowatt-hours-reactive"},
3009     { 205, "megawatt-hours-reactive"},
3010     { 206, "millimeters-of-water"},
3011     { 207, "per-mille"},
3012     { 208, "grams-per-gram"},
3013     { 209, "kilograms-per-kilogram"},
3014     { 210, "grams-per-kilogram"},
3015     { 211, "milligrams-per-gram"},
3016     { 212, "milligrams-per-kilogram"},
3017     { 213, "grams-per-milliliter"},
3018     { 214, "grams-per-liter"},
3019     { 215, "milligrams-per-liter"},
3020     { 216, "micrograms-per-liter"},
3021     { 217, "grams-per-cubic-meter"},
3022     { 218, "milligrams-per-cubic-meter"},
3023     { 219, "micrograms-per-cubic-meter"},
3024     { 220, "nanograms-per-cubic-meter"},
3025     { 221, "grams-per-cubic-centimeter"},
3026     { 222, "becquerels"},
3027     { 223, "kilobecquerels"},
3028     { 224, "megabecquerels"},
3029     { 225, "gray"},
3030     { 226, "milligray"},
3031     { 227, "microgray"},
3032     { 228, "sieverts"},
3033     { 229, "millisieverts"},
3034     { 230, "microsieverts"},
3035     { 231, "microsieverts-per-hour"},
3036     { 232, "decibels-a"},
3037     { 233, "nephelometric-turbidity-unit"},
3038     { 234, "pH"},
3039     { 235, "grams-per-square-meter"},
3040     { 236, "minutes-per-degree-kelvin"},
3041     { 0,   NULL}
3042 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
3043    Enumerated values 256-65535 may be used by others subject to
3044    the procedures and constraints described in Clause 23. */
3045 };
3046
3047 static const value_string
3048 BACnetErrorCode [] = {
3049     {   0, "other"},
3050     {   1, "authentication-failed"},
3051     {   2, "configuration-in-progress"},
3052     {   3, "device-busy"},
3053     {   4, "dynamic-creation-not-supported"},
3054     {   5, "file-access-denied"},
3055     {   6, "incompatible-security-levels"},
3056     {   7, "inconsistent-parameters"},
3057     {   8, "inconsistent-selection-criterion"},
3058     {   9, "invalid-data-type"},
3059     {  10, "invalid-file-access-method"},
3060     {  11, "invalid-file-start-position"},
3061     {  12, "invalid-operator-name"},
3062     {  13, "invalid-parameter-data-type"},
3063     {  14, "invalid-time-stamp"},
3064     {  15, "key-generation-error"},
3065     {  16, "missing-required-parameter"},
3066     {  17, "no-objects-of-specified-type"},
3067     {  18, "no-space-for-object"},
3068     {  19, "no-space-to-add-list-element"},
3069     {  20, "no-space-to-write-property"},
3070     {  21, "no-vt-sessions-available"},
3071     {  22, "property-is-not-a-list"},
3072     {  23, "object-deletion-not-permitted"},
3073     {  24, "object-identifier-already-exists"},
3074     {  25, "operational-problem"},
3075     {  26, "password-failure"},
3076     {  27, "read-access-denied"},
3077     {  28, "security-not-supported"},
3078     {  29, "service-request-denied"},
3079     {  30, "timeout"},
3080     {  31, "unknown-object"},
3081     {  32, "unknown-property"},
3082     {  33, "removed enumeration"},
3083     {  34, "unknown-vt-class"},
3084     {  35, "unknown-vt-session"},
3085     {  36, "unsupported-object-type"},
3086     {  37, "value-out-of-range"},
3087     {  38, "vt-session-already-closed"},
3088     {  39, "vt-session-termination-failure"},
3089     {  40, "write-access-denied"},
3090     {  41, "character-set-not-supported"},
3091     {  42, "invalid-array-index"},
3092     {  43, "cov-subscription-failed"},
3093     {  44, "not-cov-property"},
3094     {  45, "optional-functionality-not-supported"},
3095     {  46, "invalid-configuration-data"},
3096     {  47, "datatype-not-supported"},
3097     {  48, "duplicate-name"},
3098     {  49, "duplicate-object-id"},
3099     {  50, "property-is-not-an-array"},
3100     {  73, "invalid-event-state"},
3101     {  74, "no-alarm-configured"},
3102     {  75, "log-buffer-full"},
3103     {  76, "logged-value-purged"},
3104     {  77, "no-property-specified"},
3105     {  78, "not-configured-for-triggered-logging"},
3106     {  79, "unknown-subscription"},
3107     {  80, "parameter-out-of-range"},
3108     {  81, "list-element-not-found"},
3109     {  82, "busy"},
3110     {  83, "communication-disabled"},
3111     {  84, "success"},
3112     {  85, "access-denied"},
3113     {  86, "bad-destination-address"},
3114     {  87, "bad-destination-device-id"},
3115     {  88, "bad-signature"},
3116     {  89, "bad-source-address"},
3117     {  90, "bad-timestamp"},
3118     {  91, "cannot-use-key"},
3119     {  92, "cannot-verify-message-id"},
3120     {  93, "correct-key-revision"},
3121     {  94, "destination-device-id-required"},
3122     {  95, "duplicate-message"},
3123     {  96, "encryption-not-configured"},
3124     {  97, "encryption-required"},
3125     {  98, "incorrect-key"},
3126     {  99, "invalid-key-data"},
3127     { 100, "key-update-in-progress"},
3128     { 101, "malformed-message"},
3129     { 102, "not-key-server"},
3130     { 103, "security-not-configured"},
3131     { 104, "source-security-required"},
3132     { 105, "too-many-keys"},
3133     { 106, "unknown-authentication-type"},
3134     { 107, "unknown-key"},
3135     { 108, "unknown-key-revision"},
3136     { 109, "unknown-source-message"},
3137     { 110, "not-router-to-dnet"},
3138     { 111, "router-busy"},
3139     { 112, "unknown-network-message"},
3140     { 113, "message-too-long"},
3141     { 114, "security-error"},
3142     { 115, "addressing-error"},
3143     { 116, "write-bdt-failed"},
3144     { 117, "read-bdt-failed"},
3145     { 118, "register-foreign-device-failed"},
3146     { 119, "read-fdt-failed"},
3147     { 120, "delete-fdt-entry-failed"},
3148     { 121, "distribute-broadcast-failed"},
3149     { 122, "unknown-file-size"},
3150     { 123, "abort-apdu-too-long"},
3151     { 124, "abort-application-exceeded-reply-time"},
3152     { 125, "abort-out-of-resources"},
3153     { 126, "abort-tsm-timeout"},
3154     { 127, "abort-window-size-out-of-range"},
3155     { 128, "file-full"},
3156     { 129, "inconsistent-configuration"},
3157     { 130, "inconsistent-object-type"},
3158     { 131, "internal-error"},
3159     { 132, "not-configured"},
3160     { 133, "out-of-memory"},
3161     { 134, "value-too-long"},
3162     { 135, "abort-insufficient-security"},
3163     { 136, "abort-security-error"},
3164     { 0,   NULL}
3165 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
3166    Enumerated values 256-65535 may be used by others subject to the
3167    procedures and constraints described in Clause 23. */
3168 };
3169
3170 static const value_string
3171 BACnetPropertyIdentifier [] = {
3172     {   0, "acked-transition"},
3173     {   1, "ack-required"},
3174     {   2, "action"},
3175     {   3, "action-text"},
3176     {   4, "active-text"},
3177     {   5, "active-vt-session"},
3178     {   6, "alarm-value"},
3179     {   7, "alarm-values"},
3180     {   8, "all"},
3181     {   9, "all-write-successful"},
3182     {  10, "apdu-segment-timeout"},
3183     {  11, "apdu-timeout"},
3184     {  12, "application-software-version"},
3185     {  13, "archive"},
3186     {  14, "bias"},
3187     {  15, "change-of-state-count"},
3188     {  16, "change-of-state-time"},
3189     {  17, "notification-class"},
3190     {  18, "the property in this place was deleted"},
3191     {  19, "controlled-variable-reference"},
3192     {  20, "controlled-variable-units"},
3193     {  21, "controlled-variable-value"},
3194     {  22, "cov-increment"},
3195     {  23, "datelist"},
3196     {  24, "daylights-savings-status"},
3197     {  25, "deadband"},
3198     {  26, "derivative-constant"},
3199     {  27, "derivative-constant-units"},
3200     {  28, "description"},
3201     {  29, "description-of-halt"},
3202     {  30, "device-address-binding"},
3203     {  31, "device-type"},
3204     {  32, "effective-period"},
3205     {  33, "elapsed-active-time"},
3206     {  34, "error-limit"},
3207     {  35, "event-enable"},
3208     {  36, "event-state"},
3209     {  37, "event-type"},
3210     {  38, "exception-schedule"},
3211     {  39, "fault-values"},
3212     {  40, "feedback-value"},
3213     {  41, "file-access-method"},
3214     {  42, "file-size"},
3215     {  43, "file-type"},
3216     {  44, "firmware-revision"},
3217     {  45, "high-limit"},
3218     {  46, "inactive-text"},
3219     {  47, "in-progress"},
3220     {  48, "instance-of"},
3221     {  49, "integral-constant"},
3222     {  50, "integral-constant-units"},
3223     {  51, "issue-confirmed-notifications"},
3224     {  52, "limit-enable"},
3225     {  53, "list-of-group-members"},
3226     {  54, "list-of-object-property-references"},
3227     {  55, "list-of-session-keys"},
3228     {  56, "local-date"},
3229     {  57, "local-time"},
3230     {  58, "location"},
3231     {  59, "low-limit"},
3232     {  60, "manipulated-variable-reference"},
3233     {  61, "maximum-output"},
3234     {  62, "max-apdu-length-accepted"},
3235     {  63, "max-info-frames"},
3236     {  64, "max-master"},
3237     {  65, "max-pres-value"},
3238     {  66, "minimum-off-time"},
3239     {  67, "minimum-on-time"},
3240     {  68, "minimum-output"},
3241     {  69, "min-pres-value"},
3242     {  70, "model-name"},
3243     {  71, "modification-date"},
3244     {  72, "notify-type"},
3245     {  73, "number-of-APDU-retries"},
3246     {  74, "number-of-states"},
3247     {  75, "object-identifier"},
3248     {  76, "object-list"},
3249     {  77, "object-name"},
3250     {  78, "object-property-reference"},
3251     {  79, "object-type"},
3252     {  80, "optional"},
3253     {  81, "out-of-service"},
3254     {  82, "output-units"},
3255     {  83, "event-parameters"},
3256     {  84, "polarity"},
3257     {  85, "present-value"},
3258     {  86, "priority"},
3259     {  87, "priority-array"},
3260     {  88, "priority-for-writing"},
3261     {  89, "process-identifier"},
3262     {  90, "program-change"},
3263     {  91, "program-location"},
3264     {  92, "program-state"},
3265     {  93, "proportional-constant"},
3266     {  94, "proportional-constant-units"},
3267     {  95, "protocol-conformance-class"},
3268     {  96, "protocol-object-types-supported"},
3269     {  97, "protocol-services-supported"},
3270     {  98, "protocol-version"},
3271     {  99, "read-only"},
3272     { 100, "reason-for-halt"},
3273     { 101, "recipient"},
3274     { 102, "recipient-list"},
3275     { 103, "reliability"},
3276     { 104, "relinquish-default"},
3277     { 105, "required"},
3278     { 106, "resolution"},
3279     { 107, "segmentation-supported"},
3280     { 108, "setpoint"},
3281     { 109, "setpoint-reference"},
3282     { 110, "state-text"},
3283     { 111, "status-flags"},
3284     { 112, "system-status"},
3285     { 113, "time-delay"},
3286     { 114, "time-of-active-time-reset"},
3287     { 115, "time-of-state-count-reset"},
3288     { 116, "time-synchronization-recipients"},
3289     { 117, "units"},
3290     { 118, "update-interval"},
3291     { 119, "utc-offset"},
3292     { 120, "vendor-identifier"},
3293     { 121, "vendor-name"},
3294     { 122, "vt-class-supported"},
3295     { 123, "weekly-schedule"},
3296     { 124, "attempted-samples"},
3297     { 125, "average-value"},
3298     { 126, "buffer-size"},
3299     { 127, "client-cov-increment"},
3300     { 128, "cov-resubscription-interval"},
3301     { 129, "current-notify-time"},
3302     { 130, "event-time-stamp"},
3303     { 131, "log-buffer"},
3304     { 132, "log-device-object-property"},
3305     { 133, "enable"}, /* per ANSI/ASHRAE 135-2004 addendum B */
3306     { 134, "log-interval"},
3307     { 135, "maximum-value"},
3308     { 136, "minimum-value"},
3309     { 137, "notification-threshold"},
3310     { 138, "previous-notify-time"},
3311     { 139, "protocol-revision"},
3312     { 140, "records-since-notification"},
3313     { 141, "record-count"},
3314     { 142, "start-time"},
3315     { 143, "stop-time"},
3316     { 144, "stop-when-full"},
3317     { 145, "total-record-count"},
3318     { 146, "valid-samples"},
3319     { 147, "window-interval"},
3320     { 148, "window-samples"},
3321     { 149, "maximum-value-time-stamp"},
3322     { 150, "minimum-value-time-stamp"},
3323     { 151, "variance-value"},
3324     { 152, "active-cov-subscriptions"},
3325     { 153, "backup-failure-timeout"},
3326     { 154, "configuration-files"},
3327     { 155, "database-revision"},
3328     { 156, "direct-reading"},
3329     { 157, "last-restore-time"},
3330     { 158, "maintenance-required"},
3331     { 159, "member-of"},
3332     { 160, "mode"},
3333     { 161, "operation-expected"},
3334     { 162, "setting"},
3335     { 163, "silenced"},
3336     { 164, "tracking-value"},
3337     { 165, "zone-members"},
3338     { 166, "life-safety-alarm-values"},
3339     { 167, "max-segments-accepted"},
3340     { 168, "profile-name"},
3341     { 169, "auto-slave-discovery"},
3342     { 170, "manual-slave-address-binding"},
3343     { 171, "slave-address-binding"},
3344     { 172, "slave-proxy-enable"},
3345     { 173, "last-notify-record"},     /* bug 4117 */
3346     { 174, "schedule-default"},
3347     { 175, "accepted-modes"},
3348     { 176, "adjust-value"},
3349     { 177, "count"},
3350     { 178, "count-before-change"},
3351     { 179, "count-change-time"},
3352     { 180, "cov-period"},
3353     { 181, "input-reference"},
3354     { 182, "limit-monitoring-interval"},
3355     { 183, "logging-device"},
3356     { 184, "logging-record"},
3357     { 185, "prescale"},
3358     { 186, "pulse-rate"},
3359     { 187, "scale"},
3360     { 188, "scale-factor"},
3361     { 189, "update-time"},
3362     { 190, "value-before-change"},
3363     { 191, "value-set"},
3364     { 192, "value-change-time"},
3365     { 193, "align-intervals"},
3366     { 194, "group-member-names"},
3367     { 195, "interval-offset"},
3368     { 196, "last-restart-reason"},
3369     { 197, "logging-type"},
3370     { 198, "member-status-flags"},
3371     { 199, "notification-period"},
3372     { 200, "previous-notify-record"},
3373     { 201, "requested-update-interval"},
3374     { 202, "restart-notification-recipients"},
3375     { 203, "time-of-device-restart"},
3376     { 204, "time-synchronization-interval"},
3377     { 205, "trigger"},
3378     { 206, "UTC-time-synchronization-recipients"},
3379     { 207, "node-subtype"},
3380     { 208, "node-type"},
3381     { 209, "structured-object-list"},
3382     { 210, "subordinate-annotations"},
3383     { 211, "subordinate-list"},
3384     { 212, "actual-shed-level"},
3385     { 213, "duty-window"},
3386     { 214, "expected-shed-level"},
3387     { 215, "full-duty-baseline"},
3388     { 216, "node-subtype"},
3389     { 217, "node-type"},
3390     { 218, "requested-shed-level"},
3391     { 219, "shed-duration"},
3392     { 220, "shed-level-descriptions"},
3393     { 221, "shed-levels"},
3394     { 222, "state-description"},
3395     /* enumeration values 223-225 are unassigned */
3396     { 226, "door-alarm-state"},
3397     { 227, "door-extended-pulse-time"},
3398     { 228, "door-members"},
3399     { 229, "door-open-too-long-time"},
3400     { 230, "door-pulse-time"},
3401     { 231, "door-status"},
3402     { 232, "door-unlock-delay-time"},
3403     { 233, "lock-status"},
3404     { 234, "masked-alarm-values"},
3405     { 235, "secured-status"},
3406     /* enumeration values 236-243 are unassigned */
3407     { 244, "absentee-limit"},     /* added with addenda 135-2008j */
3408     { 245, "access-alarm-events"},
3409     { 246, "access-doors"},
3410     { 247, "access-event"},
3411     { 248, "access-event-authentication-factor"},
3412     { 249, "access-event-credential"},
3413     { 250, "access-event-time"},
3414     { 251, "access-transaction-events"},
3415     { 252, "accompaniment"},
3416     { 253, "accompaniment-time"},
3417     { 254, "activation-time"},
3418     { 255, "active-authentication-policy"},
3419     { 256, "assigned-access-rights"},
3420     { 257, "authentication-factors"},
3421     { 258, "authentication-policy-list"},
3422     { 259, "authentication-policy-names"},
3423     { 260, "authentication-status"},
3424     { 261, "authorization-mode"},
3425     { 262, "belongs-to"},
3426     { 263, "credential-disable"},
3427     { 264, "credential-status"},
3428     { 265, "credentials"},
3429     { 266, "credentials-in-zone"},
3430     { 267, "days-remaining"},
3431     { 268, "entry-points"},
3432     { 269, "exit-points"},
3433     { 270, "expiry-time"},
3434     { 271, "extended-time-enable"},
3435     { 272, "failed-attempt-events"},
3436     { 273, "failed-attempts"},
3437     { 274, "failed-attempts-time"},
3438     { 275, "last-access-event"},
3439     { 276, "last-access-point"},
3440     { 277, "last-credential-added"},
3441     { 278, "last-credential-added-time"},
3442     { 279, "last-credential-removed"},
3443     { 280, "last-credential-removed-time"},
3444     { 281, "last-use-time"},
3445     { 282, "lockout"},
3446     { 283, "lockout-relinquish-time"},
3447     { 284, "master-exemption"},
3448     { 285, "max-failed-attempts"},
3449     { 286, "members"},
3450     { 287, "muster-point"},
3451     { 288, "negative-access-rules"},
3452     { 289, "number-of-authentication-policies"},
3453     { 290, "occupancy-count"},
3454     { 291, "occupancy-count-adjust"},
3455     { 292, "occupancy-count-enable"},
3456     { 293, "occupancy-exemption"},
3457     { 294, "occupancy-lower-limit"},
3458     { 295, "occupancy-lower-limit-enforced"},
3459     { 296, "occupancy-state"},
3460     { 297, "occupancy-upper-limit"},
3461     { 298, "occupancy-upper-limit-enforced"},
3462     { 299, "passback-exemption"},
3463     { 300, "passback-mode"},
3464     { 301, "passback-timeout"},
3465     { 302, "positive-access-rules"},
3466     { 303, "reason-for-disable"},
3467     { 304, "supported-formats"},
3468     { 305, "supported-format-classes"},
3469     { 306, "threat-authority"},
3470     { 307, "threat-level"},
3471     { 308, "trace-flag"},
3472     { 309, "transaction-notification-class"},
3473     { 310, "user-external-identifier"},
3474     { 311, "user-information-reference"},
3475     /* enumeration values 312-316 are unassigned */
3476     { 317, "user-name"},
3477     { 318, "user-type"},
3478     { 319, "uses-remaining"},
3479     { 320, "zone-from"},
3480     { 321, "zone-to"},
3481     { 322, "access-event-tag"},
3482     { 323, "global-identifier"},
3483     /* enumeration values 324-325 reserved for future addenda */
3484     { 326, "verification-time"},
3485     { 327, "base-device-security-policy"},
3486     { 328, "distribution-key-revision"},
3487     { 329, "do-not-hide"},
3488     { 330, "key-sets"},
3489     { 331, "last-key-server"},
3490     { 332, "network-access-security-policies"},
3491     { 333, "packet-reorder-time"},
3492     { 334, "security-pdu-timeout"},
3493     { 335, "security-time-window"},
3494     { 336, "supported-security-algorithms"},
3495     { 337, "update-key-set-timeout"},
3496     { 338, "backup-and-restore-state"},
3497     { 339, "backup-preparation-time"},
3498     { 340, "restore-completion-time"},
3499     { 341, "restore-preparation-time"},
3500     { 342, "bit-mask"},       /* addenda 135-2008w */
3501     { 343, "bit-text"},
3502     { 344, "is-utc"},
3503     { 345, "group-members"},
3504     { 346, "group-member-names"},
3505     { 347, "member-status-flags"},
3506     { 348, "requested-update-interval"},
3507     { 349, "covu-period"},
3508     { 350, "covu-recipients"},
3509     { 351, "event-message-texts"},
3510     { 0,   NULL}
3511 /* Enumerated values 0-511 are reserved for definition by ASHRAE.
3512    Enumerated values 512-4194303 may be used by others subject to
3513    the procedures and constraints described in Clause 23. */
3514 };
3515
3516 static const value_string
3517 BACnetBinaryPV [] = {
3518     { 0, "inactive"},
3519     { 1, "active"},
3520     { 0, NULL}
3521 };
3522
3523
3524 #define ANSI_X34 0
3525 #define IBM_MS_DBCS 1
3526 #define JIS_C_6226 2
3527 #define ISO_10646_UCS4 3
3528 #define ISO_10646_UCS2 4
3529 #define ISO_18859_1 5
3530 static const value_string
3531 BACnetCharacterSet [] = {
3532     { ANSI_X34,      "ANSI X3.4 / UTF-8 (since 2010)"},
3533     { IBM_MS_DBCS,   "IBM/Microsoft DBCS"},
3534     { JIS_C_6226,    "JIS C 6226"},
3535     { ISO_10646_UCS4, "ISO 10646(UCS-4)"},
3536     { ISO_10646_UCS2, "ISO 10646(UCS-2)"},
3537     { ISO_18859_1,    "ISO 18859-1"},
3538     { 0,     NULL}
3539 };
3540
3541 static const value_string
3542 BACnetStatusFlags [] = {
3543     { 0, "in-alarm"},
3544     { 1, "fault"},
3545     { 2, "overridden"},
3546     { 3, "out-of-service"},
3547     { 0, NULL}
3548 };
3549
3550 static const value_string
3551 BACnetMessagePriority [] = {
3552     { 0, "normal"},
3553     { 1, "urgent"},
3554     { 0, NULL}
3555 };
3556
3557 static const value_string
3558 BACnetAcknowledgementFilter [] = {
3559     { 0, "all"},
3560     { 1, "acked"},
3561     { 2, "not-acked"},
3562     { 0, NULL}
3563 };
3564
3565 static const value_string
3566 BACnetResultFlags [] = {
3567     { 0, "firstitem"},
3568     { 1, "lastitem"},
3569     { 2, "moreitems"},
3570     { 0, NULL}
3571 };
3572
3573 static const value_string
3574 BACnetRelationSpecifier [] = {
3575     { 0, "equal"},
3576     { 1, "not-equal"},
3577     { 2, "less-than"},
3578     { 3, "greater-than"},
3579     { 4, "less-than-or-equal"},
3580     { 5, "greater-than-or-equal"},
3581     { 0, NULL}
3582 };
3583
3584 static const value_string
3585 BACnetSelectionLogic [] = {
3586     { 0, "and"},
3587     { 1, "or"},
3588     { 2, "all"},
3589     { 0, NULL}
3590 };
3591
3592 static const value_string
3593 BACnetEventStateFilter [] = {
3594     { 0, "offnormal"},
3595     { 1, "fault"},
3596     { 2, "normal"},
3597     { 3, "all"},
3598     { 4, "active"},
3599     { 0, NULL}
3600 };
3601
3602 static const value_string
3603 BACnetEventTransitionBits [] = {
3604     { 0, "to-offnormal"},
3605     { 1, "to-fault"},
3606     { 2, "to-normal"},
3607     { 0, NULL}
3608 };
3609
3610 static const value_string
3611 BACnetSegmentation [] = {
3612     { 0, "segmented-both"},
3613     { 1, "segmented-transmit"},
3614     { 2, "segmented-receive"},
3615     { 3, "no-segmentation"},
3616     { 0, NULL}
3617 };
3618
3619 static const value_string
3620 BACnetSilencedState [] = {
3621     { 0, "unsilenced"},
3622     { 1, "audible-silenced"},
3623     { 2, "visible-silenced"},
3624     { 3, "all-silenced"},
3625     { 0, NULL}
3626 };
3627
3628 static const value_string
3629 BACnetDeviceStatus [] = {
3630     { 0, "operational"},
3631     { 1, "operational-read-only"},
3632     { 2, "download-required"},
3633     { 3, "download-in-progress"},
3634     { 4, "non-operational"},
3635     { 5, "backup-in-progress"},
3636     { 0, NULL}
3637 };
3638
3639 static const value_string
3640 BACnetEnableDisable [] = {
3641     { 0, "enable"},
3642     { 1, "disable"},
3643     { 2, "disable-initiation"},
3644     { 0, NULL}
3645 };
3646
3647 static const value_string
3648 months [] = {
3649     {   1, "January" },
3650     {   2, "February" },
3651     {   3, "March" },
3652     {   4, "April" },
3653     {   5, "May" },
3654     {   6, "June" },
3655     {   7, "July" },
3656     {   8, "August" },
3657     {   9, "September" },
3658     {  10, "October" },
3659     {  11, "November" },
3660     {  12, "December" },
3661     { 255, "any month" },
3662     { 0,   NULL }
3663 };
3664
3665 static const value_string
3666 weekofmonth [] = {
3667     {   1, "days numbered 1-7" },
3668     {   2, "days numbered 8-14" },
3669     {   3, "days numbered 15-21" },
3670     {   4, "days numbered 22-28" },
3671     {   5, "days numbered 29-31" },
3672     {   6, "last 7 days of this month" },
3673     { 255, "any week of this month" },
3674     { 0,   NULL }
3675 };
3676
3677 /* note: notification class object recipient-list uses
3678    different day-of-week enum */
3679 static const value_string
3680 day_of_week [] = {
3681     {   1, "Monday" },
3682     {   2, "Tuesday" },
3683     {   3, "Wednesday" },
3684     {   4, "Thursday" },
3685     {   5, "Friday" },
3686     {   6, "Saturday" },
3687     {   7, "Sunday" },
3688     { 255, "any day of week" },
3689     { 0,   NULL }
3690 };
3691
3692 static const value_string
3693 BACnetErrorClass [] = {
3694     { 0, "device" },
3695     { 1, "object" },
3696     { 2, "property" },
3697     { 3, "resources" },
3698     { 4, "security" },
3699     { 5, "services" },
3700     { 6, "vt" },
3701     { 7, "communication" },
3702     { 0, NULL }
3703 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3704    Enumerated values64-65535 may be used by others subject to
3705    the procedures and constraints described in Clause 23. */
3706 };
3707
3708 static const value_string
3709 BACnetVTClass [] = {
3710     { 0, "default-terminal" },
3711     { 1, "ansi-x3-64" },
3712     { 2, "dec-vt52" },
3713     { 3, "dec-vt100" },
3714     { 4, "dec-vt200" },
3715     { 5, "hp-700-94" },
3716     { 6, "ibm-3130" },
3717     { 0, NULL }
3718 };
3719
3720 static const value_string
3721 BACnetEventType [] = {
3722     {  0, "change-of-bitstring" },
3723     {  1, "change-of-state" },
3724     {  2, "change-of-value" },
3725     {  3, "command-failure" },
3726     {  4, "floating-limit" },
3727     {  5, "out-of-range" },
3728     {  6, "complex-event-type" },
3729     {  7, "(deprecated)buffer-ready" },
3730     {  8, "change-of-life-safety" },
3731     {  9, "extended" },
3732     { 10, "buffer-ready" },
3733     { 11, "unsigned-range" },
3734     { 14, "double-out-of-range"},     /* added with addenda 135-2008w */
3735     { 15, "signed-out-of-range"},
3736     { 16, "unsigned-out-of-range"},
3737     { 17, "change-of-characterstring"},
3738     { 18, "change-of-status-flags"},
3739     { 0,  NULL }
3740 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3741    Enumerated values 64-65535 may be used by others subject to
3742    the procedures and constraints described in Clause 23.
3743    It is expected that these enumerated values will correspond
3744    to the use of the complex-event-type CHOICE [6] of the
3745    BACnetNotificationParameters production. */
3746 };
3747
3748 static const value_string
3749 BACnetEventState [] = {
3750     { 0, "normal" },
3751     { 1, "fault" },
3752     { 2, "offnormal" },
3753     { 3, "high-limit" },
3754     { 4, "low-limit" },
3755     { 5, "life-safety-alarm" },
3756     { 0, NULL }
3757 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3758    Enumerated values 64-65535 may be used by others subject to
3759    the procedures and constraints described in Clause 23.  */
3760 };
3761
3762 static const value_string
3763 BACnetLogStatus [] = {
3764     { 0, "log-disabled" },
3765     { 1, "buffer-purged" },
3766     { 2, "log-interrupted"},
3767     { 0, NULL }
3768 };
3769
3770 static const value_string
3771 BACnetMaintenance [] = {
3772     { 0, "none" },
3773     { 1, "periodic-test" },
3774     { 2, "need-service-operational" },
3775     { 3, "need-service-inoperative" },
3776     { 0, NULL }
3777 };
3778
3779 static const value_string
3780 BACnetNotifyType [] = {
3781     { 0, "alarm" },
3782     { 1, "event" },
3783     { 2, "ack-notification" },
3784     { 0, NULL }
3785 };
3786
3787 static const value_string
3788 BACnetServicesSupported [] = {
3789     {  0, "acknowledgeAlarm"},
3790     {  1, "confirmedCOVNotification"},
3791     {  2, "confirmedEventNotification"},
3792     {  3, "getAlarmSummary"},
3793     {  4, "getEnrollmentSummary"},
3794     {  5, "subscribeCOV"},
3795     {  6, "atomicReadFile"},
3796     {  7, "atomicWriteFile"},
3797     {  8, "addListElement"},
3798     {  9, "removeListElement"},
3799     { 10, "createObject"},
3800     { 11, "deleteObject"},
3801     { 12, "readProperty"},
3802     { 13, "readPropertyConditional"},
3803     { 14, "readPropertyMultiple"},
3804     { 15, "writeProperty"},
3805     { 16, "writePropertyMultiple"},
3806     { 17, "deviceCommunicationControl"},
3807     { 18, "confirmedPrivateTransfer"},
3808     { 19, "confirmedTextMessage"},
3809     { 20, "reinitializeDevice"},
3810     { 21, "vtOpen"},
3811     { 22, "vtClose"},
3812     { 23, "vtData"},
3813     { 24, "authenticate"},
3814     { 25, "requestKey"},
3815     { 26, "i-Am"},
3816     { 27, "i-Have"},
3817     { 28, "unconfirmedCOVNotification"},
3818     { 29, "unconfirmedEventNotification"},
3819     { 30, "unconfirmedPrivateTransfer"},
3820     { 31, "unconfirmedTextMessage"},
3821     { 32, "timeSynchronization"},
3822     { 33, "who-Has"},
3823     { 34, "who-Is"},
3824     { 35, "readRange"},
3825     { 36, "utcTimeSynchronization"},
3826     { 37, "lifeSafetyOperation"},
3827     { 38, "subscribeCOVProperty"},
3828     { 39, "getEventInformation"},
3829     { 0,  NULL}
3830 };
3831
3832 static const value_string
3833 BACnetPropertyStates [] = {
3834     {  0, "boolean-value"},
3835     {  1, "binary-value"},
3836     {  2, "event-type"},
3837     {  3, "polarity"},
3838     {  4, "program-change"},
3839     {  5, "program-state"},
3840     {  6, "reason-for-halt"},
3841     {  7, "reliability"},
3842     {  8, "state"},
3843     {  9, "system-status"},
3844     { 10, "units"},
3845     { 11, "unsigned-value"},
3846     { 12, "life-safety-mode"},
3847     { 13, "life-safety-state"},
3848     { 14, "restart-reason"},
3849     { 15, "door-alarm-state"},
3850     { 16, "action"},
3851     { 17, "door-secured-status"},
3852     { 18, "door-status"},
3853     { 19, "door-value"},
3854     { 20, "file-access-method"},
3855     { 21, "lock-status"},
3856     { 22, "life-safety-operation"},
3857     { 23, "maintenance"},
3858     { 24, "node-type"},
3859     { 25, "notify-type"},
3860     { 26, "security-level"},
3861     { 27, "shed-state"},
3862     { 28, "silenced-state"},
3863     /* context tag 29 reserved for future addenda */
3864     { 29, "unknown-29"},
3865     { 30, "access-event"},
3866     { 31, "zone-occupancy-state"},
3867     { 32, "access-credential-disable-reason"},
3868     { 33, "access-credential-disable"},
3869     { 34, "authentication-status"},
3870     { 35, "unknown-35"},
3871     { 36, "backup-state"},
3872     { 0, NULL}
3873 /* Tag values 0-63 are reserved for definition by ASHRAE.
3874    Tag values of 64-254 may be used by others to accommodate
3875    vendor specific properties that have discrete or enumerated values,
3876    subject to the constraints described in Clause 23. */
3877 };
3878
3879 static const value_string
3880 BACnetProgramError [] = {
3881     { 0, "normal"},
3882     { 1, "load-failed"},
3883     { 2, "internal"},
3884     { 3, "program"},
3885     { 4, "other"},
3886     { 0, NULL}
3887 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3888    Enumerated values 64-65535 may be used by others subject to
3889    the procedures and constraints described in Clause 23. */
3890 };
3891
3892 static const value_string
3893 BACnetProgramRequest [] = {
3894     { 0, "ready"},
3895     { 1, "load"},
3896     { 2, "run"},
3897     { 3, "halt"},
3898     { 4, "restart"},
3899     { 4, "unload"},
3900     { 0, NULL}
3901 };
3902
3903 static const value_string
3904 BACnetProgramState [] = {
3905     { 0, "idle"},
3906     { 1, "loading"},
3907     { 2, "running"},
3908     { 3, "waiting"},
3909     { 4, "halted"},
3910     { 4, "unloading"},
3911     { 0, NULL}
3912 };
3913
3914 static const value_string
3915 BACnetReinitializedStateOfDevice [] = {
3916     { 0, "coldstart"},
3917     { 1, "warmstart"},
3918     { 2, "startbackup"},
3919     { 3, "endbackup"},
3920     { 4, "startrestore"},
3921     { 5, "endrestore"},
3922     { 6, "abortrestore"},
3923     { 0, NULL}
3924 };
3925
3926 static const value_string
3927 BACnetPolarity [] = {
3928     { 0, "normal"},
3929     { 1, "reverse"},
3930     { 0, NULL}
3931 };
3932
3933 static const value_string
3934 BACnetTagNames[] = {
3935     { 5, "Extended Value" },
3936     { 6, "Opening Tag" },
3937     { 7, "Closing Tag" },
3938     { 0, NULL }
3939 };
3940
3941 static const value_string
3942 BACnetReadRangeOptions[] = {
3943     { 3, "range byPosition" },
3944     { 4, "range byTime" },
3945     { 5, "range timeRange" },
3946     { 6, "range bySequenceNumber" },
3947     { 7, "range byTime" },
3948     { 0, NULL }
3949 };
3950
3951 /* Present_Value for Load Control Object */
3952 static const value_string
3953 BACnetShedState[] = {
3954     { 0, "shed-inactive" },
3955     { 1, "shed-request-pending" },
3956     { 2, "shed-compliant" },
3957     { 3, "shed-non-compliant" },
3958     { 0, NULL }
3959 };
3960
3961 static const value_string
3962 BACnetNodeType [] = {
3963     { 0, "unknown" },
3964     { 1, "system" },
3965     { 2, "network" },
3966     { 3, "device" },
3967     { 4, "organizational" },
3968     { 5, "area" },
3969     { 6, "equipment" },
3970     { 7, "point" },
3971     { 8, "collection" },
3972     { 9, "property" },
3973     { 10, "functional" },
3974     { 11, "other" },
3975     { 0, NULL }
3976 };
3977
3978 static const value_string
3979 BACnetLoggingType [] = {
3980     { 0, "polled" },
3981     { 1, "cov" },
3982     { 2, "triggered" },
3983     { 0, NULL }
3984 };
3985
3986 static const value_string
3987 BACnetDoorStatus [] = {
3988     { 0, "closed" },
3989     { 1, "opened" },
3990     { 2, "unknown" },
3991     { 0, NULL }
3992 };
3993
3994 static const value_string
3995 BACnetLockStatus [] = {
3996     { 0, "locked" },
3997     { 1, "unlocked" },
3998     { 2, "fault" },
3999     { 3, "unknown" },
4000     { 0, NULL }
4001 };
4002
4003 static const value_string
4004 BACnetDoorSecuredStatus [] = {
4005     { 0, "secured" },
4006     { 1, "unsecured" },
4007     { 2, "unknown" },
4008     { 0, NULL }
4009 };
4010
4011 static const value_string
4012 BACnetDoorAlarmState [] = {
4013     { 0, "normal" },
4014     { 1, "alarm" },
4015     { 2, "door-open-too-long" },
4016     { 3, "forced-open" },
4017     { 4, "tamper" },
4018     { 5, "door-fault" },
4019     { 6, "lock-down" },
4020     { 7, "free-access" },
4021     { 8, "egress-open" },
4022     { 0, NULL }
4023 };
4024
4025 static const value_string
4026 BACnetAccumulatorStatus [] = {
4027     { 0, "normal" },
4028     { 1, "starting" },
4029     { 2, "recovered" },
4030     { 3, "abnormal" },
4031     { 4, "failed" },
4032     { 0, NULL }
4033 };
4034
4035 /* These values are (manually) transferred from
4036  * http://www.bacnet.org/VendorID/BACnet Vendor IDs.htm
4037  * Version: "As of September 16, 2013"
4038  */
4039
4040 static const value_string
4041 BACnetVendorIdentifiers [] = {
4042     {   0, "ASHRAE" },
4043     {   1, "NIST" },
4044     {   2, "The Trane Company" },
4045     {   3, "McQuay International" },
4046     {   4, "PolarSoft" },
4047     {   5, "Johnson Controls, Inc." },
4048     {   6, "American Auto-Matrix" },
4049     {   7, "Siemens Schweiz AG (Formerly: Landis & Staefa Division Europe)" },
4050     {   8, "Delta Controls" },
4051     {   9, "Siemens Schweiz AG" },
4052     {  10, "Tour Andover Controls Corporation" },
4053     {  11, "TAC" },
4054     {  12, "Orion Analysis Corporation" },
4055     {  13, "Teletrol Systems Inc." },
4056     {  14, "Cimetrics Technology" },
4057     {  15, "Cornell University" },
4058     {  16, "United Technologies Carrier" },
4059     {  17, "Honeywell Inc." },
4060     {  18, "Alerton / Honeywell" },
4061     {  19, "TAC AB" },
4062     {  20, "Hewlett-Packard Company" },
4063     {  21, "Dorsette's Inc." },
4064     {  22, "Siemens Schweiz AG (Formerly: Cerberus AG)" },
4065     {  23, "York Controls Group" },
4066     {  24, "Automated Logic Corporation" },
4067     {  25, "CSI Control Systems International" },
4068     {  26, "Phoenix Controls Corporation" },
4069     {  27, "Innovex Technologies, Inc." },
4070     {  28, "KMC Controls, Inc." },
4071     {  29, "Xn Technologies, Inc." },
4072     {  30, "Hyundai Information Technology Co., Ltd." },
4073     {  31, "Tokimec Inc." },
4074     {  32, "Simplex" },
4075     {  33, "North Building Technologies Limited" },
4076     {  34, "Notifier" },
4077     {  35, "Reliable Controls Corporation" },
4078     {  36, "Tridium Inc." },
4079     {  37, "Sierra Monitor Corporation/FieldServer Technologies" },
4080     {  38, "Silicon Energy" },
4081     {  39, "Kieback & Peter GmbH & Co KG" },
4082     {  40, "Anacon Systems, Inc." },
4083     {  41, "Systems Controls & Instruments, LLC" },
4084     {  42, "Lithonia Lighting" },
4085     {  43, "Micropower Manufacturing" },
4086     {  44, "Matrix Controls" },
4087     {  45, "METALAIRE" },
4088     {  46, "ESS Engineering" },
4089     {  47, "Sphere Systems Pty Ltd." },
4090     {  48, "Walker Technologies Corporation" },
4091     {  49, "H I Solutions, Inc." },
4092     {  50, "MBS GmbH" },
4093     {  51, "SAMSON AG" },
4094     {  52, "Badger Meter Inc." },
4095     {  53, "DAIKIN Industries Ltd." },
4096     {  54, "NARA Controls Inc." },
4097     {  55, "Mammoth Inc." },
4098     {  56, "Liebert Corporation" },
4099     {  57, "SEMCO Incorporated" },
4100     {  58, "Air Monitor Corporation" },
4101     {  59, "TRIATEK, LLC" },
4102     {  60, "NexLight" },
4103     {  61, "Multistack" },
4104     {  62, "TSI Incorporated" },
4105     {  63, "Weather-Rite, Inc." },
4106     {  64, "Dunham-Bush" },
4107     {  65, "Reliance Electric" },
4108     {  66, "LCS Inc." },
4109     {  67, "Regulator Australia PTY Ltd." },
4110     {  68, "Touch-Plate Lighting Controls" },
4111     {  69, "Amann GmbH" },
4112     {  70, "RLE Technologies" },
4113     {  71, "Cardkey Systems" },
4114     {  72, "SECOM Co., Ltd." },
4115     {  73, "ABB Gebaudetechnik AG Bereich NetServ" },
4116     {  74, "KNX Association cvba" },
4117     {  75, "Institute of Electrical Installation Engineers of Japan (IEIEJ)" },
4118     {  76, "Nohmi Bosai, Ltd." },
4119     {  77, "Carel S.p.A." },
4120     {  78, "AirSense Technology, Inc." },
4121     {  79, "Hochiki Corporation" },
4122     {  80, "Fr. Sauter AG" },
4123     {  81, "Matsushita Electric Works, Ltd." },
4124     {  82, "Mitsubishi Electric Corporation, Inazawa Works" },
4125     {  83, "Mitsubishi Heavy Industries, Ltd." },
4126     {  84, "ITT Bell & Gossett" },
4127     {  85, "Yamatake Building Systems Co., Ltd." },
4128     {  86, "The Watt Stopper, Inc." },
4129     {  87, "Aichi Tokei Denki Co., Ltd." },
4130     {  88, "Activation Technologies, LLC" },
4131     {  89, "Saia-Burgess Controls, Ltd." },
4132     {  90, "Hitachi, Ltd." },
4133     {  91, "Novar Corp./Trend Control Systems Ltd." },
4134     {  92, "Mitsubishi Electric Lighting Corporation" },
4135     {  93, "Argus Control Systems, Ltd." },
4136     {  94, "Kyuki Corporation" },
4137     {  95, "Richards-Zeta Building Intelligence, Inc." },
4138     {  96, "Scientech R&D, Inc." },
4139     {  97, "VCI Controls, Inc." },
4140     {  98, "Toshiba Corporation" },
4141     {  99, "Mitsubishi Electric Corporation Air Conditioning & Refrigeration Systems Works" },
4142     { 100, "Custom Mechanical Equipment, LLC" },
4143     { 101, "ClimateMaster" },
4144     { 102, "ICP Panel-Tec, Inc." },
4145     { 103, "D-Tek Controls" },
4146     { 104, "NEC Engineering, Ltd." },
4147     { 105, "PRIVA BV" },
4148     { 106, "Meidensha Corporation" },
4149     { 107, "JCI Systems Integration Services" },
4150     { 108, "Freedom Corporation" },
4151     { 109, "Neuberger Gebaudeautomation GmbH" },
4152     { 110, "Sitronix" },
4153     { 111, "Leviton Manufacturing" },
4154     { 112, "Fujitsu Limited" },
4155     { 113, "Emerson Network Power" },
4156     { 114, "S. A. Armstrong, Ltd." },
4157     { 115, "Visonet AG" },
4158     { 116, "M&M Systems, Inc." },
4159     { 117, "Custom Software Engineering" },
4160     { 118, "Nittan Company, Limited" },
4161     { 119, "Elutions Inc. (Wizcon Systems SAS)" },
4162     { 120, "Pacom Systems Pty., Ltd." },
4163     { 121, "Unico, Inc." },
4164     { 122, "Ebtron, Inc." },
4165     { 123, "Scada Engine" },
4166     { 124, "AC Technology Corporation" },
4167     { 125, "Eagle Technology" },
4168     { 126, "Data Aire, Inc." },
4169     { 127, "ABB, Inc." },
4170     { 128, "Transbit Sp. z o. o." },
4171     { 129, "Toshiba Carrier Corporation" },
4172     { 130, "Shenzhen Junzhi Hi-Tech Co., Ltd." },
4173     { 131, "Tokai Soft" },
4174     { 132, "Blue Ridge Technologies" },
4175     { 133, "Veris Industries" },
4176     { 134, "Centaurus Prime" },
4177     { 135, "Sand Network Systems" },
4178     { 136, "Regulvar, Inc." },
4179     { 137, "AFDtek Division of Fastek International Inc." },
4180     { 138, "PowerCold Comfort Air Solutions, Inc." },
4181     { 139, "I Controls" },
4182     { 140, "Viconics Electronics, Inc." },
4183     { 141, "Yaskawa America, Inc." },
4184     { 142, "DEOS control systems GmbH" },
4185     { 143, "Digitale Mess- und Steuersysteme AG" },
4186     { 144, "Fujitsu General Limited" },
4187     { 145, "Project Engineering S.r.l." },
4188     { 146, "Sanyo Electric Co., Ltd." },
4189     { 147, "Integrated Information Systems, Inc." },
4190     { 148, "Temco Controls, Ltd." },
4191     { 149, "Airtek International Inc." },
4192     { 150, "Advantech Corporation" },
4193     { 151, "Titan Products, Ltd." },
4194     { 152, "Regel Partners" },
4195     { 153, "National Environmental Product" },
4196     { 154, "Unitec Corporation" },
4197     { 155, "Kanden Engineering Company" },
4198     { 156, "Messner Gebaudetechnik GmbH" },
4199     { 157, "Integrated.CH" },
4200     { 158, "EH Price Limited" },
4201     { 159, "SE-Elektronic GmbH" },
4202     { 160, "Rockwell Automation" },
4203     { 161, "Enflex Corp." },
4204     { 162, "ASI Controls" },
4205     { 163, "SysMik GmbH Dresden" },
4206     { 164, "HSC Regelungstechnik GmbH" },
4207     { 165, "Smart Temp Australia Pty. Ltd." },
4208     { 166, "Cooper Controls" },
4209     { 167, "Duksan Mecasys Co., Ltd." },
4210     { 168, "Fuji IT Co., Ltd." },
4211     { 169, "Vacon Plc" },
4212     { 170, "Leader Controls" },
4213     { 171, "Cylon Controls, Ltd." },
4214     { 172, "Compas" },
4215     { 173, "Mitsubishi Electric Building Techno-Service Co., Ltd." },
4216     { 174, "Building Control Integrators" },
4217     { 175, "ITG Worldwide (M) Sdn Bhd" },
4218     { 176, "Lutron Electronics Co., Inc." },
4219     { 178, "LOYTEC Electronics GmbH" },
4220     { 179, "ProLon" },
4221     { 180, "Mega Controls Limited" },
4222     { 181, "Micro Control Systems, Inc." },
4223     { 182, "Kiyon, Inc." },
4224     { 183, "Dust Networks" },
4225     { 184, "Advanced Building Automation Systems" },
4226     { 185, "Hermos AG" },
4227     { 186, "CEZIM" },
4228     { 187, "Softing" },
4229     { 188, "Lynxspring" },
4230     { 189, "Schneider Toshiba Inverter Europe" },
4231     { 190, "Danfoss Drives A/S" },
4232     { 191, "Eaton Corporation" },
4233     { 192, "Matyca S.A." },
4234     { 193, "Botech AB" },
4235     { 194, "Noveo, Inc." },
4236     { 195, "AMEV" },
4237     { 196, "Yokogawa Electric Corporation" },
4238     { 197, "GFR Gesellschaft fur Regelungstechnik" },
4239     { 198, "Exact Logic" },
4240     { 199, "Mass Electronics Pty Ltd dba Innotech Control Systems Australia" },
4241     { 200, "Kandenko Co., Ltd." },
4242     { 201, "DTF, Daten-Technik Fries" },
4243     { 202, "Klimasoft, Ltd." },
4244     { 203, "Toshiba Schneider Inverter Corporation" },
4245     { 204, "Control Applications, Ltd." },
4246     { 205, "KDT Systems Co., Ltd." },
4247     { 206, "Onicon Incorporated" },
4248     { 207, "Automation Displays, Inc." },
4249     { 208, "Control Solutions, Inc." },
4250     { 209, "Remsdaq Limited" },
4251     { 210, "NTT Facilities, Inc." },
4252     { 211, "VIPA GmbH" },
4253     { 212, "TSC21 Association of Japan" },
4254     { 213, "Strato Automation" },
4255     { 214, "HRW Limited" },
4256     { 215, "Lighting Control & Design, Inc." },
4257     { 216, "Mercy Electronic and Electrical Industries" },
4258     { 217, "Samsung SDS Co., Ltd" },
4259     { 218, "Impact Facility Solutions, Inc." },
4260     { 219, "Aircuity" },
4261     { 220, "Control Techniques, Ltd." },
4262     { 221, "OpenGeneral Pty., Ltd." },
4263     { 222, "WAGO Kontakttechnik GmbH & Co. KG" },
4264     { 223, "Cerus Industrial" },
4265     { 224, "Chloride Power Protection Company" },
4266     { 225, "Computrols, Inc." },
4267     { 226, "Phoenix Contact GmbH & Co. KG" },
4268     { 227, "Grundfos Management A/S" },
4269     { 228, "Ridder Drive Systems" },
4270     { 229, "Soft Device SDN BHD" },
4271     { 230, "Integrated Control Technology Limited" },
4272     { 231, "AIRxpert Systems, Inc." },
4273     { 232, "Microtrol Limited" },
4274     { 233, "Red Lion Controls" },
4275     { 234, "Digital Electronics Corporation" },
4276     { 235, "Ennovatis GmbH" },
4277     { 236, "Serotonin Software Technologies, Inc." },
4278     { 237, "LS Industrial Systems Co., Ltd." },
4279     { 238, "Square D Company" },
4280     { 239, "S Squared Innovations, Inc." },
4281     { 240, "Aricent Ltd." },
4282     { 241, "EtherMetrics, LLC" },
4283     { 242, "Industrial Control Communications, Inc." },
4284     { 243, "Paragon Controls, Inc." },
4285     { 244, "A. O. Smith Corporation" },
4286     { 245, "Contemporary Control Systems, Inc." },
4287     { 246, "Intesis Software SL" },
4288     { 247, "Ingenieurgesellschaft N. Hartleb mbH" },
4289     { 248, "Heat-Timer Corporation" },
4290     { 249, "Ingrasys Technology, Inc." },
4291     { 250, "Costerm Building Automation" },
4292     { 251, "WILO SE" },
4293     { 252, "Embedia Technologies Corp." },
4294     { 253, "Technilog" },
4295     { 254, "HR Controls Ltd. & Co. KG" },
4296     { 255, "Lennox International, Inc." },
4297     { 256, "RK-Tec Rauchklappen-Steuerungssysteme GmbH & Co. KG" },
4298     { 257, "Thermomax, Ltd." },
4299     { 258, "ELCON Electronic Control, Ltd." },
4300     { 259, "Larmia Control AB" },
4301     { 260, "BACnet Stack at SourceForge" },
4302     { 261, "G4S Security Services A/S" },
4303     { 262, "Exor International S.p.A." },
4304     { 263, "Cristal Controles" },
4305     { 264, "Regin AB" },
4306     { 265, "Dimension Software, Inc." },
4307     { 266, "SynapSense Corporation" },
4308     { 267, "Beijing Nantree Electronic Co., Ltd." },
4309     { 268, "Camus Hydronics Ltd." },
4310     { 269, "Kawasaki Heavy Industries, Ltd." },
4311     { 270, "Critical Environment Technologies" },
4312     { 271, "ILSHIN IBS Co., Ltd." },
4313     { 272, "ELESTA Energy Control AG" },
4314     { 273, "KROPMAN Installatietechniek" },
4315     { 274, "Baldor Electric Company" },
4316     { 275, "INGA mbH" },
4317     { 276, "GE Consumer & Industrial" },
4318     { 277, "Functional Devices, Inc." },
4319     { 278, "ESAC" },
4320     { 279, "M-System Co., Ltd." },
4321     { 280, "Yokota Co., Ltd." },
4322     { 281, "Hitranse Technology Co., LTD" },
4323     { 282, "Federspiel Controls" },
4324     { 283, "Kele, Inc." },
4325     { 284, "Opera Electronics, Inc." },
4326     { 285, "Gentec" },
4327     { 286, "Embedded Science Labs, LLC" },
4328     { 287, "Parker Hannifin Corporation" },
4329     { 288, "MaCaPS International Limited" },
4330     { 289, "Link4 Corporation" },
4331     { 290, "Romutec Steuer-u. Regelsysteme GmbH" },
4332     { 291, "Pribusin, Inc." },
4333     { 292, "Advantage Controls" },
4334     { 293, "Critical Room Control" },
4335     { 294, "LEGRAND" },
4336     { 295, "Tongdy Control Technology Co., Ltd." },
4337     { 296, "ISSARO Integrierte Systemtechnik" },
4338     { 297, "Pro-Dev Industries" },
4339     { 298, "DRI-STEEM" },
4340     { 299, "Creative Electronic GmbH" },
4341     { 300, "Swegon AB" },
4342     { 301, "Jan Brachacek" },
4343     { 302, "Hitachi Appliances, Inc." },
4344     { 303, "Real Time Automation, Inc." },
4345     { 304, "ITEC Hankyu-Hanshin Co." },
4346     { 305, "Cyrus E&M Engineering Co., Ltd." },
4347     { 306, "Racine Federated, Inc." },
4348     { 307, "Cirrascale Corporation" },
4349     { 308, "Elesta GmbH Building Automation" },
4350     { 309, "Securiton" },
4351     { 310, "OSlsoft, Inc." },
4352     { 311, "Hanazeder Electronic GmbH" },
4353     { 312, "Honeywell Security Deutschland, Novar GmbH" },
4354     { 313, "Siemens Energy & Automation, Inc." },
4355     { 314, "ETM Professional Control GmbH" },
4356     { 315, "Meitav-tec, Ltd." },
4357     { 316, "Janitza Electronics GmbH" },
4358     { 317, "MKS Nordhausen" },
4359     { 318, "De Gier Drive Systems B.V." },
4360     { 319, "Cypress Envirosystems" },
4361     { 320, "SMARTron s.r.o." },
4362     { 321, "Verari Systems, Inc." },
4363     { 322, "K-W Electronic Service, Inc." },
4364     { 323, "ALFA-SMART Energy Management" },
4365     { 324, "Telkonet, Inc." },
4366     { 325, "Securiton GmbH" },
4367     { 326, "Cemtrex, Inc." },
4368     { 327, "Performance Technologies, Inc." },
4369     { 328, "Xtralis (Aust) Pty Ltd" },
4370     { 329, "TROX GmbH" },
4371     { 330, "Beijing Hysine Technology Co., Ltd" },
4372     { 331, "RCK Controls, Inc." },
4373     { 332, "Distech Controls SAS" },
4374     { 333, "Novar/Honeywell" },
4375     { 334, "The S4 Group, Inc." },
4376     { 335, "Schneider Electric" },
4377     { 336, "LHA Systems" },
4378     { 337, "GHM engineering Group, Inc." },
4379     { 338, "Cllimalux S.A." },
4380     { 339, "VAISALA Oyj" },
4381     { 340, "COMPLEX (Beijing) Technology, Co., LTD." },
4382     { 341, "SCADAmetrics" },
4383     { 342, "POWERPEG NSI Limited" },
4384     { 343, "BACnet Interoperability Testing Services, Inc." },
4385     { 344, "Teco a.s." },
4386     { 345, "Plexus Technology, Inc." },
4387     { 346, "Energy Focus, Inc." },
4388     { 347, "Powersmiths International Corp." },
4389     { 348, "Nichibei Co., Ltd." },
4390     { 349, "HKC Technology Ltd." },
4391     { 350, "Ovation Networks, Inc." },
4392     { 351, "Setra Systems" },
4393     { 352, "AVG Automation" },
4394     { 353, "ZXC Ltd." },
4395     { 354, "Byte Sphere" },
4396     { 355, "Generiton Co., Ltd." },
4397     { 356, "Holter Regelarmaturen GmbH & Co. KG" },
4398     { 357, "Bedford Instruments, LLC" },
4399     { 358, "Standair Inc." },
4400     { 359, "WEG Automation - R&D" },
4401     { 360, "Prolon Control Systems ApS" },
4402     { 361, "Inneasoft" },
4403     { 362, "ConneXSoft GmbH" },
4404     { 363, "CEAG Notlichtsysteme GmbH" },
4405     { 364, "Distech Controls Inc." },
4406     { 365, "Industrial Technology Research Institute" },
4407     { 366, "ICONICS, Inc." },
4408     { 367, "IQ Controls s.c." },
4409     { 368, "OJ Electronics A/S" },
4410     { 369, "Rolbit Ltd." },
4411     { 370, "Synapsys Solutions Ltd." },
4412     { 371, "ACME Engineering Prod. Ltd." },
4413     { 372, "Zener Electric Pty, Ltd." },
4414     { 373, "Selectronix, Inc." },
4415     { 374, "Gorbet & Banerjee, LLC." },
4416     { 375, "IME" },
4417     { 376, "Stephen H. Dawson Computer Service" },
4418     { 377, "Accutrol, LLC" },
4419     { 378, "Schneider Elektronik GmbH" },
4420     { 379, "Alpha-Inno Tec GmbH" },
4421     { 380, "ADMMicro, Inc." },
4422     { 381, "Greystone Energy Systems, Inc." },
4423     { 382, "CAP Technologie" },
4424     { 383, "KeRo Systems" },
4425     { 384, "Domat Control System s.r.o." },
4426     { 385, "Efektronics Pty. Ltd." },
4427     { 386, "Hekatron Vertriebs GmbH" },
4428     { 387, "Securiton AG" },
4429     { 388, "Carlo Gavazzi Controls SpA" },
4430     { 389, "Chipkin Automation Systems" },
4431     { 390, "Savant Systems, LLC" },
4432     { 391, "Simmtronic Lighting Controls" },
4433     { 392, "Abelko Innovation AB" },
4434     { 393, "Seresco Technologies Inc." },
4435     { 394, "IT Watchdogs" },
4436     { 395, "Automation Assist Japan Corp." },
4437     { 396, "Thermokon Sensortechnik GmbH" },
4438     { 397, "EGauge Systems, LLC" },
4439     { 398, "Quantum Automation (ASIA) PTE, Ltd." },
4440     { 399, "Toshiba Lighting & Technology Corp." },
4441     { 400, "SPIN Engenharia de Automaca Ltda." },
4442     { 401, "Logistics Systems & Software Services India PVT. Ltd." },
4443     { 402, "Delta Controls Integration Products" },
4444     { 403, "Focus Media" },
4445     { 404, "LUMEnergi Inc." },
4446     { 405, "Kara Systems" },
4447     { 406, "RF Code, Inc." },
4448     { 407, "Fatek Automation Corp." },
4449     { 408, "JANDA Software Company, LLC" },
4450     { 409, "Open System Solutions Limited" },
4451     { 410, "Intelec Systems PTY Ltd." },
4452     { 411, "Ecolodgix, LLC" },
4453     { 412, "Douglas Lighting Controls" },
4454     { 413, "iSAtech GmbH" },
4455     { 414, "AREAL" },
4456     { 415, "Beckhoff Automation GmbH" },
4457     { 416, "IPAS GmbH" },
4458     { 417, "KE2 Therm Solutions" },
4459     { 418, "Base2Products" },
4460     { 419, "DTL Controls, LLC" },
4461     { 420, "INNCOM International, Inc." },
4462     { 421, "BTR Netcom GmbH" },
4463     { 422, "Greentrol Automation, Inc" },
4464     { 423, "BELIMO Automation AG" },
4465     { 424, "Samsung Heavy Industries Co, Ltd" },
4466     { 425, "Triacta Power Technologies, Inc." },
4467     { 426, "Globestar Systems" },
4468     { 427, "MLB Advanced Media, LP" },
4469     { 428, "SWG Stuckmann Wirtschaftliche Gebaudesysteme GmbH" },
4470     { 429, "SensorSwitch" },
4471     { 430, "Multitek Power Limited" },
4472     { 431, "Aquametro AG" },
4473     { 432, "LG Electronics Inc." },
4474     { 433, "Electronic Theatre Controls, Inc." },
4475     { 434, "Mitsubishi Electric Corporation Nagoya Works" },
4476     { 435, "Delta Electronics, Inc." },
4477     { 436, "Elma Kurtalj, Ltd." },
4478     { 437, "ADT Fire and Security Sp. A.o.o." },
4479     { 438, "Nedap Security Management" },
4480     { 439, "ESC Automation Inc." },
4481     { 440, "DSP4YOU Ltd." },
4482     { 441, "GE Sensing and Inspection Technologies" },
4483     { 442, "Embedded Systems SIA" },
4484     { 443, "BEFEGA GmbH" },
4485     { 444, "Baseline Inc." },
4486     { 445, "M2M Systems Integrators" },
4487     { 446, "OEMCtrl" },
4488     { 447, "Clarkson Controls Limited" },
4489     { 448, "Rogerwell Control System Limited" },
4490     { 449, "SCL Elements" },
4491     { 450, "Hitachi Ltd." },
4492     { 451, "Newron System SA" },
4493     { 452, "BEVECO Gebouwautomatisering BV" },
4494     { 453, "Streamside Solutions" },
4495     { 454, "Yellowstone Soft" },
4496     { 455, "Oztech Intelligent Systems Pty Ltd." },
4497     { 456, "Novelan GmbH" },
4498     { 457, "Flexim Americas Corporation" },
4499     { 458, "ICP DAS Co., Ltd." },
4500     { 459, "CARMA Industries Inc." },
4501     { 460, "Log-One Ltd." },
4502     { 461, "TECO Electric & Machinery Co., Ltd." },
4503     { 462, "ConnectEx, Inc." },
4504     { 463, "Turbo DDC Sudwest" },
4505     { 464, "Quatrosense Environmental Ltd." },
4506     { 465, "Fifth Light Technology Ltd." },
4507     { 466, "Scientific Solutions, Ltd." },
4508     { 467, "Controller Area Network Solutions (M) Sdn Bhd" },
4509     { 468, "RESOL - Elektronische Regelungen GmbH" },
4510     { 469, "RPBUS LLC" },
4511     { 470, "BRS Sistemas Eletronicos" },
4512     { 471, "WindowMaster A/S" },
4513     { 472, "Sunlux Technologies Ltd." },
4514     { 473, "Measurlogic" },
4515     { 474, "Frimat GmbH" },
4516     { 475, "Spirax Sarco" },
4517     { 476, "Luxtron" },
4518     { 477, "Raypak Inc" },
4519     { 478, "Air Monitor Corporation" },
4520     { 479, "Regler Och Webbteknik Sverige (ROWS)" },
4521     { 480, "Intelligent Lighting Controls Inc." },
4522     { 481, "Sanyo Electric Industry Co., Ltd" },
4523     { 482, "E-Mon Energy Monitoring Products" },
4524     { 483, "Digital Control Systems" },
4525     { 484, "ATI Airtest Technologies, Inc." },
4526     { 485, "SCS SA" },
4527     { 486, "HMS Industrial Networks AB" },
4528     { 487, "Shenzhen Universal Intellisys Co Ltd" },
4529     { 488, "EK Intellisys Sdn Bhd" },
4530     { 489, "SysCom" },
4531     { 490, "Firecom, Inc." },
4532     { 491, "ESA Elektroschaltanlagen Grimma GmbH" },
4533     { 492, "Kumahira Co Ltd" },
4534     { 493, "Hotraco" },
4535     { 494, "SABO Elektronik GmbH" },
4536     { 495, "Equip'Trans" },
4537     { 496, "TCS Basys Controls" },
4538     { 497, "FlowCon International A/S" },
4539     { 498, "ThyssenKrupp Elevator Americas" },
4540     { 499, "Abatement Technologies" },
4541     { 500, "Continental Control Systems, LLC" },
4542     { 501, "WISAG Automatisierungstechnik GmbH & Co KG" },
4543     { 502, "EasyIO" },
4544     { 503, "EAP-Electric GmbH" },
4545     { 504, "Hardmeier" },
4546     { 505, "Mircom Group of Companies" },
4547     { 506, "Quest Controls" },
4548     { 507, "Mestek, Inc" },
4549     { 508, "Pulse Energy" },
4550     { 509, "Tachikawa Corporation" },
4551     { 510, "University of Nebraska-Lincoln" },
4552     { 511, "Redwood Systems" },
4553     { 512, "PASStec Industrie-Elektronik GmbH" },
4554     { 513, "NgEK, Inc." },
4555     { 514, "FAW Electronics Ltd" },
4556     { 515, "Jireh Energy Tech Co., Ltd." },
4557     { 516, "Enlighted Inc." },
4558     { 517, "El-Piast Sp. Z o.o" },
4559     { 518, "NetxAutomation Software GmbH" },
4560     { 519, "Invertek Drives" },
4561     { 520, "Deutschmann Automation GmbH & Co. KG" },
4562     { 521, "EMU Electronic AG" },
4563     { 522, "Phaedrus Limited" },
4564     { 523, "Sigmatek GmbH & Co KG" },
4565     { 524, "Marlin Controls" },
4566     { 525, "Circutor, SA" },
4567     { 526, "UTC Fire & Security" },
4568     { 527, "DENT Instruments, Inc." },
4569     { 528, "FHP Manufacturing Company - Bosch Group" },
4570     { 529, "GE Intelligent Platforms" },
4571     { 530, "Inner Range Pty Ltd" },
4572     { 531, "GLAS Energy Technology" },
4573     { 532, "MSR-Electronic-GmbH" },
4574     { 533, "Energy Control Systems, Inc." },
4575     { 534, "EMT Controls" },
4576     { 535, "Daintree Networks Inc." },
4577     { 536, "EURO ICC d.o.o" },
4578     { 537, "TE Connectivity Energy" },
4579     { 538, "GEZE GmbH" },
4580     { 539, "NEC Corporation" },
4581     { 540, "Ho Cheung International Company Limited" },
4582     { 541, "Sharp Manufacturing Systems Corporation" },
4583     { 542, "DOT CONTROLS a.s." },
4584     { 543, "BeaconMedaes" },
4585     { 544, "Midea Commercial Aircon" },
4586     { 545, "WattMaster Controls" },
4587     { 546, "Kamstrup A/S" },
4588     { 547, "CA Computer Automation GmbH" },
4589     { 548, "Laars Heating Systems Company" },
4590     { 549, "Hitachi Systems, Ltd." },
4591     { 550, "Fushan AKE Electronic Engineering Co., Ltd." },
4592     { 551, "Toshiba International Corporation" },
4593     { 552, "Starman Systems, LLC" },
4594     { 553, "Samsung Techwin Co., Ltd." },
4595     { 554, "ISAS-Integrated Switchgear and Systems P/L" },
4596     { 556, "Obvius" },
4597     { 557, "Marek Guzik" },
4598     { 558, "Vortek Instruments, LLC" },
4599     { 559, "Universal Lighting Technologies" },
4600     { 560, "Myers Power Products, Inc." },
4601     { 561, "Vector Controls GmbH" },
4602     { 562, "Crestron Electronics, Inc." },
4603     { 563, "A&E Controls Limited" },
4604     { 564, "Projektomontaza A.D." },
4605     { 565, "Freeaire Refrigeration" },
4606     { 566, "Aqua Cooler Pty Limited" },
4607     { 567, "Basic Controls" },
4608     { 568, "GE Measurement and Control Solutions Advanced Sensors" },
4609     { 569, "EQUAL Networks" },
4610     { 570, "Millennial Net" },
4611     { 571, "APLI Ltd" },
4612     { 572, "Electro Industries/GaugeTech" },
4613     { 573, "SangMyung University" },
4614     { 574, "Coppertree Analytics, Inc." },
4615     { 575, "CoreNetiX GmbH" },
4616     { 576, "Acutherm" },
4617     { 577, "Dr. Riedel Automatisierungstechnik GmbH" },
4618     { 578, "Shina System Co., Ltd" },
4619     { 579, "Iqapertus" },
4620     { 580, "PSE Technology" },
4621     { 581, "BA Systems" },
4622     { 582, "BTICINO" },
4623     { 583, "Monico, Inc." },
4624     { 584, "iCue" },
4625     { 585, "tekmar Control Systems Ltd." },
4626     { 586, "Control Technology Corporation" },
4627     { 587, "GFAE GmbH" },
4628     { 588, "BeKa Software GmbH" },
4629     { 589, "Isoil Industria SpA" },
4630     { 590, "Home Systems Consulting SpA" },
4631     { 591, "Socomec" },
4632     { 592, "Everex Communications, Inc." },
4633     { 593, "Ceiec Electric Technology" },
4634     { 594, "Atrila GmbH" },
4635     { 595, "WingTechs" },
4636     { 596, "Shenzhen Mek Intellisys Pte Ltd." },
4637     { 597, "Nestfield Co., Ltd." },
4638     { 598, "Swissphone Telecom AG" },
4639     { 599, "PNTECH JSC" },
4640     { 600, "Horner APG, LLC" },
4641     { 601, "PVI Industries, LLC" },
4642     { 602, "Ela-compil" },
4643     { 603, "Pegasus Automation International LLC" },
4644     { 604, "Wight Electronic Services Ltd." },
4645     { 605, "Marcom" },
4646     { 606, "Exhausto A/S" },
4647     { 607, "Dwyer Instruments, Inc." },
4648     { 608, "Link GmbH" },
4649     { 609, "Oppermann Regelgerate GmbH" },
4650     { 610, "NuAire, Inc." },
4651     { 611, "Nortec Humidity, Inc." },
4652     { 612, "Bigwood Systems, Inc." },
4653     { 613, "Enbala Power Networks" },
4654     { 614, "Inter Energy Co., Ltd." },
4655     { 615, "ETC" },
4656     { 616, "COMELEC S.A.R.L" },
4657     { 617, "Pythia Technologies" },
4658     { 618, "TrendPoint Systems, Inc." },
4659     { 619, "AWEX" },
4660     { 620, "Eurevia" },
4661     { 621, "Kongsberg E-lon AS" },
4662     { 622, "FlaktWoods" },
4663     { 623, "E + E Elektronik GES M.B.H." },
4664     { 624, "ARC Informatique" },
4665     { 625, "SKIDATA AG" },
4666     { 626, "WSW Solutions" },
4667     { 627, "Trefon Electronic GmbH" },
4668     { 628, "Dongseo System" },
4669     { 629, "Kanontec Intelligence Technology Co., Ltd." },
4670     { 630, "EVCO S.p.A." },
4671     { 631, "Accuenergy (CANADA) Inc." },
4672     { 632, "SoftDEL" },
4673     { 633, "Orion Energy Systems, Inc." },
4674     { 634, "Roboticsware" },
4675     { 635, "DOMIQ Sp. z o.o." },
4676     { 636, "Solidyne" },
4677     { 637, "Elecsys Corporation" },
4678     { 638, "Conditionaire International Pty. Limited" },
4679     { 639, "Quebec, Inc." },
4680     { 640, "Homerun Holdings" },
4681     { 641, "RFM, Inc." },
4682     { 642, "Comptek" },
4683     { 643, "Westco Systems, Inc." },
4684     { 644, "Advancis Software & Services GmbH" },
4685     { 645, "Intergrid, LLC" },
4686     { 646, "Markerr Controls, Inc." },
4687     { 647, "Toshiba Elevator and Building Systems Corporation" },
4688     { 648, "Spectrum Controls, Inc." },
4689     { 649, "Mkservice" },
4690     { 650, "Fox Thermal Instruments" },
4691     { 651, "SyxthSense Ltd" },
4692     { 652, "DUHA System S R.O." },
4693     { 653, "NIBE" },
4694     { 654, "Melink Corporation" },
4695     { 655, "Fritz-Haber-Institut" },
4696     { 656, "MTU Onsite Energy GmbH, Gas Power Systems" },
4697     { 657, "Omega Engineering, Inc." },
4698     { 658, "Avelon" },
4699     { 659, "Ywire Technologies, Inc." },
4700     { 660, "M.R. Engineering Co., Ltd." },
4701     { 661, "Lochinvar, LLC" },
4702     { 662, "Sontay Limited" },
4703     { 663, "GRUPA Slawomir Chelminski" },
4704     { 664, "Arch Meter Corporation" },
4705     { 665, "Senva, Inc." },
4706     { 667, "FM-Tec" },
4707     { 668, "Systems Specialists, Inc." },
4708     { 669, "SenseAir" },
4709     { 670, "AB IndustrieTechnik Srl" },
4710     { 671, "Cortland Research, LLC" },
4711     { 672, "MediaView" },
4712     { 673, "VDA Elettronica" },
4713     { 674, "CSS, Inc." },
4714     { 675, "Tek-Air Systems, Inc." },
4715     { 676, "ICDT" },
4716     { 677, "The Armstrong Monitoring Corporation" },
4717     { 678, "DIXELL S.r.l" },
4718     { 679, "Lead System, Inc." },
4719     { 680, "ISM EuroCenter S.A." },
4720     { 681, "TDIS" },
4721     { 682, "Trade FIDES" },
4722     { 683, "Knurr GmbH (Emerson Network Power)" },
4723     { 684, "Resource Data Management" },
4724     { 685, "Abies Technology, Inc." },
4725     { 686, "Amalva" },
4726     { 687, "MIRAE Electrical Mfg. Co., Ltd." },
4727     { 688, "HunterDouglas Architectural Projects Scandinavia ApS" },
4728     { 689, "RUNPAQ Group Co., Ltd" },
4729     { 690, "Unicard SA" },
4730     { 691, "IE Technologies" },
4731     { 692, "Ruskin Manufacturing" },
4732     { 693, "Calon Associates Limited" },
4733     { 694, "Contec Co., Ltd." },
4734     { 0, NULL }
4735 };
4736 static value_string_ext BACnetVendorIdentifiers_ext = VALUE_STRING_EXT_INIT(BACnetVendorIdentifiers);
4737
4738 static int proto_bacapp = -1;
4739 static int hf_bacapp_type = -1;
4740 static int hf_bacapp_pduflags = -1;
4741 static int hf_bacapp_SEG = -1;
4742 static int hf_bacapp_MOR = -1;
4743 static int hf_bacapp_SA = -1;
4744 static int hf_bacapp_response_segments = -1;
4745 static int hf_bacapp_max_adpu_size = -1;
4746 static int hf_bacapp_invoke_id = -1;
4747 static int hf_bacapp_objectType = -1;
4748 static int hf_bacapp_instanceNumber = -1;
4749 static int hf_bacapp_sequence_number = -1;
4750 static int hf_bacapp_window_size = -1;
4751 static int hf_bacapp_service = -1;
4752 static int hf_bacapp_NAK = -1;
4753 static int hf_bacapp_SRV = -1;
4754 static int hf_Device_Instance_Range_Low_Limit = -1;
4755 static int hf_Device_Instance_Range_High_Limit = -1;
4756 static int hf_BACnetRejectReason = -1;
4757 static int hf_BACnetAbortReason = -1;
4758 static int hf_BACnetApplicationTagNumber = -1;
4759 static int hf_BACnetContextTagNumber = -1;
4760 static int hf_BACnetExtendedTagNumber = -1;
4761 static int hf_BACnetNamedTag = -1;
4762 static int hf_BACnetTagClass = -1;
4763 static int hf_BACnetCharacterSet = -1;
4764 static int hf_bacapp_tag_lvt = -1;
4765 static int hf_bacapp_tag_ProcessId = -1;
4766 static int hf_bacapp_uservice = -1;
4767 static int hf_BACnetPropertyIdentifier = -1;
4768 static int hf_BACnetVendorIdentifier = -1;
4769 static int hf_BACnetRestartReason = -1;
4770 static int hf_bacapp_tag_IPV4 = -1;
4771 static int hf_bacapp_tag_IPV6 = -1;
4772 static int hf_bacapp_tag_PORT = -1;
4773 /* some more variables for segmented messages */
4774 static int hf_msg_fragments = -1;
4775 static int hf_msg_fragment = -1;
4776 static int hf_msg_fragment_overlap = -1;
4777 static int hf_msg_fragment_overlap_conflicts = -1;
4778 static int hf_msg_fragment_multiple_tails = -1;
4779 static int hf_msg_fragment_too_long_fragment = -1;
4780 static int hf_msg_fragment_error = -1;
4781 static int hf_msg_fragment_count = -1;
4782 static int hf_msg_reassembled_in = -1;
4783 static int hf_msg_reassembled_length = -1;
4784
4785 static gint ett_msg_fragment = -1;
4786 static gint ett_msg_fragments = -1;
4787
4788 static gint ett_bacapp = -1;
4789 static gint ett_bacapp_control = -1;
4790 static gint ett_bacapp_tag = -1;
4791 static gint ett_bacapp_list = -1;
4792 static gint ett_bacapp_value = -1;
4793
4794 static expert_field ei_bacapp_bad_length = EI_INIT;
4795
4796 static gint32 propertyIdentifier = -1;
4797 static gint32 propertyArrayIndex = -1;
4798 static guint32 object_type = 4096;
4799
4800 static guint8 bacapp_flags = 0;
4801 static guint8 bacapp_seq = 0;
4802
4803 /* Defined to allow vendor identifier registration of private transfer dissectors */
4804 static dissector_table_t bacapp_dissector_table;
4805
4806
4807 /* Stat: BACnet Packets sorted by IP */
4808 bacapp_info_value_t bacinfo;
4809
4810 static const gchar* st_str_packets_by_ip = "BACnet Packets by IP";
4811 static const gchar* st_str_packets_by_ip_dst = "By Destination";
4812 static const gchar* st_str_packets_by_ip_src = "By Source";
4813 static int st_node_packets_by_ip = -1;
4814 static int st_node_packets_by_ip_dst = -1;
4815 static int st_node_packets_by_ip_src = -1;
4816
4817 static void
4818 bacapp_packet_stats_tree_init(stats_tree* st)
4819 {
4820     st_node_packets_by_ip = stats_tree_create_pivot(st, st_str_packets_by_ip, 0);
4821     st_node_packets_by_ip_src = stats_tree_create_node(st, st_str_packets_by_ip_src, st_node_packets_by_ip, TRUE);
4822     st_node_packets_by_ip_dst = stats_tree_create_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, TRUE);
4823 }
4824
4825 static int
4826 bacapp_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4827 {
4828     int    packets_for_this_dst;
4829     int    packets_for_this_src;
4830     int    service_for_this_dst;
4831     int    service_for_this_src;
4832     int    src_for_this_dst;
4833     int    dst_for_this_src;
4834     int    objectid_for_this_dst;
4835     int    objectid_for_this_src;
4836     int    instanceid_for_this_dst;
4837     int    instanceid_for_this_src;
4838     gchar *dststr;
4839     gchar *srcstr;
4840     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4841
4842     srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", address_to_str(&pinfo->src), NULL);
4843     dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", address_to_str(&pinfo->dst), NULL);
4844
4845     tick_stat_node(st, st_str_packets_by_ip, 0, TRUE);
4846     packets_for_this_dst = tick_stat_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, TRUE);
4847     packets_for_this_src = tick_stat_node(st, st_str_packets_by_ip_src, st_node_packets_by_ip, TRUE);
4848     src_for_this_dst     = tick_stat_node(st, dststr, packets_for_this_dst, TRUE);
4849     dst_for_this_src     = tick_stat_node(st, srcstr, packets_for_this_src, TRUE);
4850     service_for_this_src = tick_stat_node(st, dststr, dst_for_this_src, TRUE);
4851     service_for_this_dst = tick_stat_node(st, srcstr, src_for_this_dst, TRUE);
4852     if (binfo->service_type) {
4853         objectid_for_this_dst = tick_stat_node(st, binfo->service_type, service_for_this_dst, TRUE);
4854         objectid_for_this_src = tick_stat_node(st, binfo->service_type, service_for_this_src, TRUE);
4855         if (binfo->object_ident) {
4856             instanceid_for_this_dst = tick_stat_node(st, binfo->object_ident, objectid_for_this_dst, TRUE);
4857             tick_stat_node(st, binfo->instance_ident, instanceid_for_this_dst, FALSE);
4858             instanceid_for_this_src = tick_stat_node(st, binfo->object_ident, objectid_for_this_src, TRUE);
4859             tick_stat_node(st, binfo->instance_ident, instanceid_for_this_src, FALSE);
4860         }
4861     }
4862
4863     return 1;
4864 }
4865
4866 /* Stat: BACnet Packets sorted by Service */
4867 static const gchar* st_str_packets_by_service = "BACnet Packets by Service";
4868 static int st_node_packets_by_service = -1;
4869
4870 static void
4871 bacapp_service_stats_tree_init(stats_tree* st)
4872 {
4873     st_node_packets_by_service = stats_tree_create_pivot(st, st_str_packets_by_service, 0);
4874 }
4875
4876 static int
4877 bacapp_stats_tree_service(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4878 {
4879     int    servicetype;
4880     int    src, dst;
4881     int    objectid;
4882
4883     gchar *dststr;
4884     gchar *srcstr;
4885
4886     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4887
4888     srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", address_to_str(&pinfo->src), NULL);
4889     dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", address_to_str(&pinfo->dst), NULL);
4890
4891     tick_stat_node(st, st_str_packets_by_service, 0, TRUE);
4892     if (binfo->service_type) {
4893         servicetype = tick_stat_node(st, binfo->service_type, st_node_packets_by_service, TRUE);
4894         src         = tick_stat_node(st, srcstr, servicetype, TRUE);
4895         dst         = tick_stat_node(st, dststr, src, TRUE);
4896         if (binfo->object_ident) {
4897             objectid = tick_stat_node(st, binfo->object_ident, dst, TRUE);
4898             tick_stat_node(st, binfo->instance_ident, objectid, FALSE);
4899         }
4900     }
4901
4902     return 1;
4903 }
4904
4905 /* Stat: BACnet Packets sorted by Object Type */
4906 static const gchar* st_str_packets_by_objectid = "BACnet Packets by Object Type";
4907 static int st_node_packets_by_objectid = -1;
4908
4909 static void
4910 bacapp_objectid_stats_tree_init(stats_tree* st)
4911 {
4912     st_node_packets_by_objectid = stats_tree_create_pivot(st, st_str_packets_by_objectid, 0);
4913 }
4914
4915 static int
4916 bacapp_stats_tree_objectid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4917 {
4918     int    servicetype;
4919     int    src, dst;
4920     int    objectid;
4921
4922     gchar *dststr;
4923     gchar *srcstr;
4924     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4925
4926     srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", address_to_str(&pinfo->src), NULL);
4927     dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", address_to_str(&pinfo->dst), NULL);
4928
4929     tick_stat_node(st, st_str_packets_by_objectid, 0, TRUE);
4930     if (binfo->object_ident) {
4931         objectid = tick_stat_node(st, binfo->object_ident, st_node_packets_by_objectid, TRUE);
4932         src = tick_stat_node(st, srcstr, objectid, TRUE);
4933         dst = tick_stat_node(st, dststr, src, TRUE);
4934         if (binfo->service_type) {
4935             servicetype = tick_stat_node(st, binfo->service_type, dst, TRUE);
4936             tick_stat_node(st, binfo->instance_ident, servicetype, FALSE);
4937         }
4938     }
4939
4940     return 1;
4941 }
4942
4943 /* Stat: BACnet Packets sorted by Instance No */
4944 static const gchar* st_str_packets_by_instanceid  = "BACnet Packets by Instance ID";
4945 static int          st_node_packets_by_instanceid = -1;
4946
4947 static void
4948 bacapp_instanceid_stats_tree_init(stats_tree* st)
4949 {
4950     st_node_packets_by_instanceid = stats_tree_create_pivot(st, st_str_packets_by_instanceid, 0);
4951 }
4952
4953 static int
4954 bacapp_stats_tree_instanceid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4955 {
4956     int    servicetype;
4957     int    src, dst;
4958     int    instanceid;
4959
4960     gchar *dststr;
4961     gchar *srcstr;
4962     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4963
4964     srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", address_to_str(&pinfo->src), NULL);
4965     dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", address_to_str(&pinfo->dst), NULL);
4966
4967     tick_stat_node(st, st_str_packets_by_instanceid, 0, TRUE);
4968     if (binfo->object_ident) {
4969         instanceid = tick_stat_node(st, binfo->instance_ident, st_node_packets_by_instanceid, TRUE);
4970         src = tick_stat_node(st, srcstr, instanceid, TRUE);
4971         dst = tick_stat_node(st, dststr, src, TRUE);
4972         if (binfo->service_type) {
4973             servicetype = tick_stat_node(st, binfo->service_type, dst, TRUE);
4974             tick_stat_node(st, binfo->object_ident, servicetype, FALSE);
4975         }
4976     }
4977     return 1;
4978 }
4979
4980
4981 /* register all BACnet Ststistic trees */
4982 static void
4983 register_bacapp_stat_trees(void)
4984 {
4985     stats_tree_register("bacapp", "bacapp_ip", "BACnet/Packets sorted by IP", 0,
4986         bacapp_stats_tree_packet, bacapp_packet_stats_tree_init, NULL);
4987     stats_tree_register("bacapp", "bacapp_service", "BACnet/Packets sorted by Service", 0,
4988         bacapp_stats_tree_service, bacapp_service_stats_tree_init, NULL);
4989     stats_tree_register("bacapp", "bacapp_objectid", "BACnet/Packets sorted by Object Type", 0,
4990         bacapp_stats_tree_objectid, bacapp_objectid_stats_tree_init, NULL);
4991     stats_tree_register("bacapp", "bacapp_instanceid", "BACnet/Packets sorted by Instance ID", 0,
4992         bacapp_stats_tree_instanceid, bacapp_instanceid_stats_tree_init, NULL);
4993 }
4994
4995 /* 'data' must be ep_ allocated */
4996 static gint
4997 updateBacnetInfoValue(gint whichval, const gchar *data)
4998 {
4999     if (whichval == BACINFO_SERVICE) {
5000         bacinfo.service_type = data;
5001         return 0;
5002     }
5003     if (whichval == BACINFO_INVOKEID) {
5004         bacinfo.invoke_id = data;
5005         return 0;
5006     }
5007     if (whichval == BACINFO_OBJECTID) {
5008         bacinfo.object_ident = data;
5009         return 0;
5010     }
5011     if (whichval == BACINFO_INSTANCEID) {
5012         bacinfo.instance_ident = data;
5013         return 0;
5014     }
5015     return -1;
5016 }
5017
5018 static const fragment_items msg_frag_items = {
5019     /* Fragment subtrees */
5020     &ett_msg_fragment,
5021     &ett_msg_fragments,
5022     /* Fragment fields */
5023     &hf_msg_fragments,
5024     &hf_msg_fragment,
5025     &hf_msg_fragment_overlap,
5026     &hf_msg_fragment_overlap_conflicts,
5027     &hf_msg_fragment_multiple_tails,
5028     &hf_msg_fragment_too_long_fragment,
5029     &hf_msg_fragment_error,
5030     &hf_msg_fragment_count,
5031     /* Reassembled in field */
5032     &hf_msg_reassembled_in,
5033     /* Reassembled length field */
5034     &hf_msg_reassembled_length,
5035     /* Reassembled data field */
5036     NULL,
5037     /* Tag */
5038     "Message fragments"
5039 };
5040
5041 /* if BACnet uses the reserved values, then patch the corresponding values here, maximum 16 values are defined */
5042 static const guint MaxAPDUSize [] = { 50, 128, 206, 480, 1024, 1476 };
5043
5044 #if 0
5045 /* FIXME: fGetMaxAPDUSize is commented out, as it is not used. It was used to set variables which were not later used. */
5046 static guint
5047 fGetMaxAPDUSize(guint8 idx)
5048 {
5049     /* only 16 values are defined, so use & 0x0f */
5050     /* check the size of the Array, deliver either the entry
5051        or the first entry if idx is outside of the array (bug 3736 comment#7) */
5052
5053     if ((idx & 0x0f) >= (gint)(sizeof(MaxAPDUSize)/sizeof(guint)))
5054         return MaxAPDUSize[0];
5055     else
5056         return MaxAPDUSize[idx & 0x0f];
5057 }
5058 #endif
5059
5060
5061 /* Used when there are ranges of reserved and proprietary enumerations */
5062 static const char*
5063 val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
5064     const char *fmt, const char *split_fmt)
5065 {
5066     if (val < split_val)
5067         return val_to_str(val, vs, fmt);
5068     else
5069         return val_to_str(val, vs, split_fmt);
5070 }
5071
5072 /* from clause 20.2.1.3.2 Constructed Data */
5073 /* returns true if the extended value is used */
5074 static gboolean
5075 tag_is_extended_value(guint8 tag)
5076 {
5077     return (tag & 0x07) == 5;
5078 }
5079
5080 static gboolean
5081 tag_is_opening(guint8 tag)
5082 {
5083     return (tag & 0x07) == 6;
5084 }
5085
5086 static gboolean
5087 tag_is_closing(guint8 tag)
5088 {
5089     return (tag & 0x07) == 7;
5090 }
5091
5092 /* from clause 20.2.1.1 Class
5093    class bit shall be one for context specific tags */
5094 /* returns true if the tag is context specific */
5095 static gboolean
5096 tag_is_context_specific(guint8 tag)
5097 {
5098     return (tag & 0x08) != 0;
5099 }
5100
5101 static gboolean
5102 tag_is_extended_tag_number(guint8 tag)
5103 {
5104     return ((tag & 0xF0) == 0xF0);
5105 }
5106
5107 static guint32
5108 object_id_type(guint32 object_identifier)
5109 {
5110     return ((object_identifier >> 22) & 0x3FF);
5111 }
5112
5113 static guint32
5114 object_id_instance(guint32 object_identifier)
5115 {
5116     return (object_identifier & 0x3FFFFF);
5117 }
5118
5119 static guint
5120 fTagNo(tvbuff_t *tvb, guint offset)
5121 {
5122     return (guint)(tvb_get_guint8(tvb, offset) >> 4);
5123 }
5124
5125 static gboolean
5126 fUnsigned32(tvbuff_t *tvb, guint offset, guint32 lvt, guint32 *val)
5127 {
5128     gboolean valid = TRUE;
5129
5130     switch (lvt) {
5131     case 1:
5132         *val = tvb_get_guint8(tvb, offset);
5133         break;
5134     case 2:
5135         *val = tvb_get_ntohs(tvb, offset);
5136         break;
5137     case 3:
5138         *val = tvb_get_ntoh24(tvb, offset);
5139         break;
5140     case 4:
5141         *val = tvb_get_ntohl(tvb, offset);
5142         break;
5143     default:
5144         valid = FALSE;
5145         break;
5146     }
5147
5148     return valid;
5149 }
5150
5151 static gboolean
5152 fUnsigned64(tvbuff_t *tvb, guint offset, guint32 lvt, guint64 *val)
5153 {
5154     gboolean valid = FALSE;
5155     gint64   value = 0;
5156     guint8   data, i;
5157
5158     if (lvt && (lvt <= 8)) {
5159         valid = TRUE;
5160         for (i = 0; i < lvt; i++) {
5161             data = tvb_get_guint8(tvb, offset+i);
5162             value = (value << 8) + data;
5163         }
5164         *val = value;
5165     }
5166
5167     return valid;
5168 }
5169
5170 /* BACnet Signed Value uses 2's complement notation, but with a twist:
5171    All signed integers shall be encoded in the smallest number of octets
5172    possible.  That is, the first octet of any multi-octet encoded value
5173    shall not be X'00' if the most significant bit (bit 7) of the second
5174    octet is 0, and the first octet shall not be X'FF' if the most
5175    significant bit of the second octet is 1. ASHRAE-135-2004-20.2.5 */
5176 static gboolean
5177 fSigned64(tvbuff_t *tvb, guint offset, guint32 lvt, gint64 *val)
5178 {
5179     gboolean valid = FALSE;
5180     gint64   value = 0;
5181     guint8   data;
5182     guint32  i;
5183
5184     /* we can only handle 7 bytes for a 64-bit value due to signed-ness */
5185     if (lvt && (lvt <= 7)) {
5186         valid = TRUE;
5187         data = tvb_get_guint8(tvb, offset);
5188         if ((data & 0x80) != 0)
5189             value = (-1 << 8) | data;
5190         else
5191             value = data;
5192         for (i = 1; i < lvt; i++) {
5193             data = tvb_get_guint8(tvb, offset+i);
5194             value = (value << 8) + data;
5195         }
5196         *val = value;
5197     }
5198
5199     return valid;
5200 }
5201
5202 static guint
5203 fTagHeaderTree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5204     guint offset, guint8 *tag_no, guint8* tag_info, guint32 *lvt)
5205 {
5206     proto_item *ti = NULL;
5207     guint8      tag;
5208     guint8      value;
5209     guint       tag_len = 1;
5210     guint       lvt_len = 1;    /* used for tree display of lvt */
5211     guint       lvt_offset;     /* used for tree display of lvt */
5212
5213     lvt_offset = offset;
5214     tag        = tvb_get_guint8(tvb, offset);
5215     *tag_info  = 0;
5216     *lvt       = tag & 0x07;
5217
5218     /* To solve the problem of lvt values of 6/7 being indeterminate - it */
5219     /* can mean open/close tag or length of 6/7 after the length is */
5220     /* computed below - store whole tag info, not just context bit. */
5221     if (tag_is_context_specific(tag)) *tag_info = tag & 0x0F;
5222     *tag_no = tag >> 4;
5223     if (tag_is_extended_tag_number(tag)) {
5224         *tag_no = tvb_get_guint8(tvb, offset + tag_len++);
5225     }
5226     if (tag_is_extended_value(tag)) {       /* length is more than 4 Bytes */
5227         lvt_offset += tag_len;
5228         value = tvb_get_guint8(tvb, lvt_offset);
5229         tag_len++;
5230         if (value == 254) { /* length is encoded with 16 Bits */
5231             *lvt = tvb_get_ntohs(tvb, lvt_offset+1);
5232             tag_len += 2;
5233             lvt_len += 2;
5234         } else if (value == 255) { /* length is encoded with 32 Bits */
5235             *lvt = tvb_get_ntohl(tvb, lvt_offset+1);
5236             tag_len += 4;
5237             lvt_len += 4;
5238         } else
5239             *lvt = value;
5240     }
5241
5242     if (tree) {
5243         proto_tree *subtree;
5244         if (tag_is_opening(tag))
5245             ti = proto_tree_add_text(tree, tvb, offset, tag_len, "{[%u]", *tag_no );
5246         else if (tag_is_closing(tag))
5247             ti = proto_tree_add_text(tree, tvb, offset, tag_len, "}[%u]", *tag_no );
5248         else if (tag_is_context_specific(tag)) {
5249             ti = proto_tree_add_text(tree, tvb, offset, tag_len,
5250                                      "Context Tag: %u, Length/Value/Type: %u",
5251                                      *tag_no, *lvt);
5252         } else
5253             ti = proto_tree_add_text(tree, tvb, offset, tag_len,
5254                                      "Application Tag: %s, Length/Value/Type: %u",
5255                                      val_to_str(*tag_no,
5256                                                 BACnetApplicationTagNumber,
5257                                                 ASHRAE_Reserved_Fmt),
5258                                      *lvt);
5259
5260         /* details if needed */
5261         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5262         proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, ENC_BIG_ENDIAN);
5263         if (tag_is_extended_tag_number(tag)) {
5264             proto_tree_add_uint_format(subtree,
5265                                        hf_BACnetContextTagNumber,
5266                                        tvb, offset, 1, tag,
5267                                        "Extended Tag Number");
5268             proto_tree_add_item(subtree,
5269                                 hf_BACnetExtendedTagNumber,
5270                                 tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5271         } else {
5272             if (tag_is_context_specific(tag))
5273                 proto_tree_add_item(subtree,
5274                                     hf_BACnetContextTagNumber,
5275                                     tvb, offset, 1, ENC_BIG_ENDIAN);
5276             else
5277                 proto_tree_add_item(subtree,
5278                                     hf_BACnetApplicationTagNumber,
5279                                     tvb, offset, 1, ENC_BIG_ENDIAN);
5280         }
5281         if (tag_is_closing(tag) || tag_is_opening(tag))
5282             proto_tree_add_item(subtree,
5283                                 hf_BACnetNamedTag,
5284                                 tvb, offset, 1, ENC_BIG_ENDIAN);
5285         else if (tag_is_extended_value(tag)) {
5286             proto_tree_add_item(subtree,
5287                                 hf_BACnetNamedTag,
5288                                 tvb, offset, 1, ENC_BIG_ENDIAN);
5289             proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
5290                                 tvb, lvt_offset, lvt_len, *lvt);
5291         } else
5292             proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
5293                                 tvb, lvt_offset, lvt_len, *lvt);
5294     } /* if (tree) */
5295
5296     if (*lvt > tvb_length(tvb)) {
5297         expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
5298                                "LVT length too long: %d > %d", *lvt,
5299                                tvb_length(tvb));
5300         *lvt = 1;
5301     }
5302
5303     return tag_len;
5304 }
5305
5306 static guint
5307 fTagHeader(tvbuff_t *tvb, packet_info *pinfo, guint offset, guint8 *tag_no, guint8* tag_info,
5308     guint32 *lvt)
5309 {
5310     return fTagHeaderTree(tvb, pinfo, NULL, offset, tag_no, tag_info, lvt);
5311 }
5312
5313 static guint
5314 fNullTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5315 {
5316     guint8      tag_no, tag_info;
5317     guint32     lvt;
5318     proto_item *ti;
5319     proto_tree *subtree;
5320
5321     ti      = proto_tree_add_text(tree, tvb, offset, 1, "%sNULL", label);
5322     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5323     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5324
5325     return offset + 1;
5326 }
5327
5328 static guint
5329 fBooleanTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5330 {
5331     guint8      tag_no, tag_info;
5332     guint32     lvt      = 0;
5333     proto_item *ti;
5334     proto_tree *subtree;
5335     guint       bool_len = 1;
5336
5337     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5338     if (tag_info && lvt == 1) {
5339         lvt = tvb_get_guint8(tvb, offset+1);
5340         ++bool_len;
5341     }
5342
5343     ti = proto_tree_add_text(tree, tvb, offset, bool_len,
5344                              "%s%s", label, lvt == 0 ? "FALSE" : "TRUE");
5345     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5346     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5347
5348     return offset + bool_len;
5349 }
5350
5351 static guint
5352 fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5353 {
5354     guint64     val = 0;
5355     guint8      tag_no, tag_info;
5356     guint32     lvt;
5357     guint       tag_len;
5358     proto_item *ti;
5359     proto_tree *subtree;
5360
5361     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5362     /* only support up to an 8 byte (64-bit) integer */
5363     if (fUnsigned64(tvb, offset + tag_len, lvt, &val))
5364         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5365             "%s(Unsigned) %" G_GINT64_MODIFIER "u", label, val);
5366     else
5367         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5368             "%s - %u octets (Unsigned)", label, lvt);
5369     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5370     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5371
5372     return offset+tag_len+lvt;
5373 }
5374
5375 static guint
5376 fDevice_Instance(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, int hf)
5377 {
5378     guint8      tag_no, tag_info;
5379     guint32     lvt, safe_lvt;
5380     guint       tag_len;
5381     proto_item *ti;
5382     proto_tree *subtree;
5383
5384     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5385
5386     if (lvt > 4)
5387         safe_lvt = 4;
5388     else
5389         safe_lvt = lvt;
5390
5391     ti = proto_tree_add_item(tree, hf, tvb, offset+tag_len, safe_lvt, ENC_BIG_ENDIAN);
5392
5393     if (lvt != safe_lvt)
5394         expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
5395                 "This field claims to be an impossible %u bytes, while the max is %u", lvt, safe_lvt);
5396
5397     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5398     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5399
5400     return offset+tag_len+lvt;
5401 }
5402
5403 /* set split_val to zero when not needed */
5404 static guint
5405 fEnumeratedTagSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5406     guint offset, const gchar *label, const value_string *vs, guint32 split_val)
5407 {
5408     guint32     val = 0;
5409     guint8      tag_no, tag_info;
5410     guint32     lvt;
5411     guint       tag_len;
5412     proto_item *ti;
5413     proto_tree *subtree;
5414
5415     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5416     /* only support up to a 4 byte (32-bit) enumeration */
5417     if (fUnsigned32(tvb, offset+tag_len, lvt, &val)) {
5418         if (vs)
5419             ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5420                 "%s %s", label, val_to_split_str(val, split_val, vs,
5421                 ASHRAE_Reserved_Fmt, Vendor_Proprietary_Fmt));
5422         else
5423             ti =proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5424                 "%s %u", label, val);
5425     } else {
5426         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5427             "%s - %u octets (enumeration)", label, lvt);
5428     }
5429     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5430     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5431
5432     return offset+tag_len+lvt;
5433 }
5434
5435 static guint
5436 fEnumeratedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5437         guint offset, const gchar *label, const value_string *vs)
5438 {
5439     return fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, vs, 0);
5440 }
5441
5442 static guint
5443 fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5444 {
5445     gint64      val = 0;
5446     guint8      tag_no, tag_info;
5447     guint32     lvt;
5448     guint       tag_len;
5449     proto_item *ti;
5450     proto_tree *subtree;
5451
5452     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5453     if (fSigned64(tvb, offset + tag_len, lvt, &val))
5454         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5455             "%s(Signed) %" G_GINT64_MODIFIER "d", label, val);
5456     else
5457         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5458             "%s - %u octets (Signed)", label, lvt);
5459     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5460     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5461
5462     return offset+tag_len+lvt;
5463 }
5464
5465 static guint
5466 fRealTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5467 {
5468     guint8      tag_no, tag_info;
5469     guint32     lvt;
5470     guint       tag_len;
5471     gfloat      f_val;
5472     proto_item *ti;
5473     proto_tree *subtree;
5474
5475     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5476     f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
5477     ti = proto_tree_add_text(tree, tvb, offset, 4+tag_len,
5478         "%s%f (Real)", label, f_val);
5479     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5480     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5481
5482     return offset+tag_len+4;
5483 }
5484
5485 static guint
5486 fDoubleTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5487 {
5488     guint8 tag_no, tag_info;
5489     guint32 lvt;
5490     guint tag_len;
5491     gdouble d_val;
5492     proto_item *ti;
5493     proto_tree *subtree;
5494
5495     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5496     d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
5497     ti = proto_tree_add_text(tree, tvb, offset, 8+tag_len,
5498         "%s%f (Double)", label, d_val);
5499     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5500     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5501
5502     return offset+tag_len+8;
5503 }
5504
5505 static guint
5506 fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5507 {
5508     guint32     val = 0, lvt;
5509     guint8      tag_no, tag_info;
5510     proto_item *ti;
5511     proto_tree *subtree;
5512     guint       tag_len;
5513
5514     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5515     if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
5516         ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
5517             tvb, offset, lvt+tag_len, val);
5518     else
5519         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5520             "Process Identifier - %u octets (Signed)", lvt);
5521     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5522     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5523     offset += tag_len + lvt;
5524
5525     return offset;
5526 }
5527
5528 static guint
5529 fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5530 {
5531     guint32     val = 0, lvt;
5532     guint8      tag_no, tag_info;
5533     proto_item *ti;
5534     proto_tree *subtree;
5535     guint       tag_len;
5536
5537     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5538     if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
5539         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5540         "%s (hh.mm.ss): %d.%02d.%02d%s",
5541         label,
5542         (val / 3600), ((val % 3600) / 60), (val % 60),
5543         val == 0 ? " (indefinite)" : "");
5544     else
5545         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5546             "%s - %u octets (Signed)", label, lvt);
5547     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5548     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5549
5550     return offset+tag_len+lvt;
5551 }
5552
5553 static guint
5554 fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5555 {
5556     guint32     month, weekOfMonth, dayOfWeek;
5557     guint8      tag_no, tag_info;
5558     guint32     lvt;
5559     guint       tag_len;
5560     proto_item *ti;
5561     proto_tree *subtree;
5562
5563     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5564     month = tvb_get_guint8(tvb, offset+tag_len);
5565     weekOfMonth = tvb_get_guint8(tvb, offset+tag_len+1);
5566     dayOfWeek = tvb_get_guint8(tvb, offset+tag_len+2);
5567     ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s %s, %s",
5568                  val_to_str(month, months, "month (%d) not found"),
5569                  val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"),
5570                  val_to_str(dayOfWeek, day_of_week, "day of week (%d) not found"));
5571     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5572     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5573
5574     return offset+tag_len+lvt;
5575 }
5576
5577 static guint
5578 fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5579 {
5580     guint32     year, month, day, weekday;
5581     guint8      tag_no, tag_info;
5582     guint32     lvt;
5583     guint       tag_len;
5584     proto_item *ti;
5585     proto_tree *subtree;
5586
5587     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5588     year    = tvb_get_guint8(tvb, offset+tag_len);
5589     month   = tvb_get_guint8(tvb, offset+tag_len+1);
5590     day     = tvb_get_guint8(tvb, offset+tag_len+2);
5591     weekday = tvb_get_guint8(tvb, offset+tag_len+3);
5592     if ((year == 255) && (day == 255) && (month == 255) && (weekday == 255)) {
5593         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5594             "%sany", label);
5595     }
5596     else if (year != 255) {
5597         year += 1900;
5598         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5599             "%s%s %d, %d, (Day of Week = %s)",
5600             label, val_to_str(month,
5601                 months,
5602                 "month (%d) not found"),
5603             day, year, val_to_str(weekday,
5604                 day_of_week,
5605                 "(%d) not found"));
5606     } else {
5607         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5608             "%s%s %d, any year, (Day of Week = %s)",
5609             label, val_to_str(month, months, "month (%d) not found"),
5610             day, val_to_str(weekday, day_of_week, "(%d) not found"));
5611     }
5612     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5613     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5614
5615     return offset+tag_len+lvt;
5616 }
5617
5618 static guint
5619 fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5620 {
5621     guint32     hour, minute, second, msec, lvt;
5622     guint8      tag_no, tag_info;
5623     guint       tag_len;
5624     proto_item *ti;
5625     proto_tree *subtree;
5626
5627     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5628     hour    = tvb_get_guint8(tvb, offset+tag_len);
5629     minute  = tvb_get_guint8(tvb, offset+tag_len+1);
5630     second  = tvb_get_guint8(tvb, offset+tag_len+2);
5631     msec    = tvb_get_guint8(tvb, offset+tag_len+3);
5632     if ((hour == 255) && (minute == 255) && (second == 255) && (msec == 255))
5633         ti = proto_tree_add_text(tree, tvb, offset,
5634             lvt+tag_len, "%sany", label);
5635     else
5636         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5637             "%s%d:%02d:%02d.%d %s = %02d:%02d:%02d.%d",
5638             label,
5639             hour > 12 ? hour - 12 : hour,
5640             minute, second, msec,
5641             hour >= 12 ? "P.M." : "A.M.",
5642             hour, minute, second, msec);
5643     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5644     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5645
5646     return offset+tag_len+lvt;
5647 }
5648
5649 static guint
5650 fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5651 {
5652     proto_tree *subtree = tree;
5653     proto_item *tt;
5654
5655     if (label != NULL) {
5656         tt = proto_tree_add_text(subtree, tvb, offset, 10, "%s", label);
5657         subtree = proto_item_add_subtree(tt, ett_bacapp_value);
5658     }
5659     offset = fDate(tvb, pinfo, subtree, offset, "Date: ");
5660     return fTime(tvb, pinfo, subtree, offset, "Time: ");
5661 }
5662
5663 static guint
5664 fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5665 {
5666     guint lastoffset = 0;
5667     guint8 tag_no, tag_info;
5668     guint32 lvt;
5669
5670     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
5671         lastoffset = offset;
5672         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5673         if (tag_is_closing(tag_info)) {   /* closing Tag, but not for me */
5674             return offset;
5675         }
5676         offset = fTime(tvb, pinfo, tree, offset, "Time: ");
5677         offset = fApplicationTypes(tvb, pinfo, tree, offset, "Value: ");
5678
5679         if (offset == lastoffset) break;    /* exit loop if nothing happens inside */
5680     }
5681     return offset;
5682 }
5683
5684 static guint
5685 fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5686 {
5687     guint8  tag_no, tag_info;
5688     guint32 lvt;
5689
5690     switch (fTagNo(tvb, offset)) {
5691     case 0: /* Date */
5692         offset = fDate(tvb, pinfo, tree, offset, "Date: ");
5693         break;
5694     case 1: /* dateRange */
5695         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5696         offset  = fDateRange(tvb, pinfo, tree, offset);
5697         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5698         break;
5699     case 2: /* BACnetWeekNDay */
5700         offset = fWeekNDay(tvb, pinfo, tree, offset);
5701         break;
5702     default:
5703         return offset;
5704     }
5705
5706     return offset;
5707 }
5708
5709 static guint
5710 fEventTimeStamps( tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
5711 {
5712     guint32     lvt     = 0;
5713     proto_tree* subtree = tree;
5714     proto_item* ti      = 0;
5715
5716     if (tvb_reported_length_remaining(tvb, offset) > 0) {
5717         ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventTimeStamps");
5718         if (ti) {
5719             subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5720         }
5721         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
5722         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
5723         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
5724     }
5725     return offset;
5726 }
5727
5728 static guint
5729 fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5730 {
5731     guint8  tag_no = 0, tag_info = 0;
5732     guint32 lvt    = 0;
5733
5734     if (tvb_reported_length_remaining(tvb, offset) > 0) {   /* don't loop, it's a CHOICE */
5735         switch (fTagNo(tvb, offset)) {
5736         case 0: /* time */
5737             offset = fTime(tvb, pinfo, tree, offset, label?label:"time: ");
5738             break;
5739         case 1: /* sequenceNumber */
5740             offset = fUnsignedTag(tvb, pinfo, tree, offset,
5741                 label?label:"sequence number: ");
5742             break;
5743         case 2: /* dateTime */
5744             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5745             offset  = fDateTime(tvb, pinfo, tree, offset, label?label:"date time: ");
5746             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5747             break;
5748         default:
5749             return offset;
5750         }
5751     }
5752
5753     return offset;
5754 }
5755
5756
5757 static guint
5758 fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5759 {
5760     if (tvb_reported_length_remaining(tvb, offset) > 0) {
5761         offset = fApplicationTypes(tvb, pinfo, tree, offset, "increment: ");
5762     }
5763     return offset;
5764 }
5765
5766 static const value_string
5767 BACnetDaysOfWeek [] = {
5768     { 0, "Monday" },
5769     { 1, "Tuesday" },
5770     { 2, "Wednesday" },
5771     { 3, "Thursday" },
5772     { 4, "Friday" },
5773     { 5, "Saturday" },
5774     { 6, "Sunday" },
5775     { 0, NULL }
5776 };
5777
5778 static guint
5779 fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5780 {
5781     if (tvb_reported_length_remaining(tvb, offset) > 0) {
5782         offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
5783                                              "valid Days: ", BACnetDaysOfWeek);
5784         offset = fTime(tvb, pinfo, tree, offset, "from time: ");
5785         offset = fTime(tvb, pinfo, tree, offset, "to time: ");
5786         offset = fRecipient(tvb, pinfo, tree, offset);
5787         offset = fProcessId(tvb, pinfo, tree, offset);
5788         offset = fApplicationTypes(tvb, pinfo, tree, offset,
5789                                     "issue confirmed notifications: ");
5790         offset = fBitStringTagVS(tvb, pinfo, tree, offset,
5791                                   "transitions: ", BACnetEventTransitionBits);
5792     }
5793     return offset;
5794 }
5795
5796
5797 static guint
5798 fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
5799 {
5800     gchar      *tmp;
5801     guint       start   = offset;
5802     guint8      tag_no, tag_info;
5803     proto_tree *subtree = tree;
5804     proto_item *ti      = 0;
5805
5806     offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5807
5808     if (lvt > 0) {
5809         tmp = tvb_bytes_to_str(tvb, offset, lvt);
5810         ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s %s", label, tmp);
5811         offset += lvt;
5812     }
5813
5814     if (ti)
5815         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5816
5817     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
5818
5819     return offset;
5820 }
5821
5822 static guint
5823 fMacAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
5824 {
5825     gchar *tmp;
5826     guint start = offset;
5827     guint8 tag_no, tag_info;
5828     proto_tree* subtree = tree;
5829     proto_item* ti;
5830
5831     offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5832
5833     ti = proto_tree_add_text(tree, tvb, offset, 6, "%s", label); /* just add the label, with the tagHeader information in its subtree */
5834
5835     if (lvt > 0) {
5836         if (lvt == 6) { /* we have 6 Byte IP Address with 4 Octets IPv4 and 2 Octets Port Information */
5837
5838             guint32 ip   = tvb_get_ipv4(tvb, offset);
5839             guint16 port = tvb_get_ntohs(tvb, offset+4);
5840
5841             proto_tree_add_ipv4(tree, hf_bacapp_tag_IPV4, tvb, offset, 4, ip);
5842             proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+4, 2, port);
5843
5844         } else {
5845             if (lvt == 18) { /* we have 18 Byte IP Address with 16 Octets IPv6 and 2 Octets Port Information */
5846             struct e_in6_addr addr;
5847             guint16 port =  tvb_get_ntohs(tvb, offset+16);
5848             tvb_get_ipv6(tvb, offset, &addr);
5849
5850             proto_tree_add_ipv6(tree, hf_bacapp_tag_IPV6, tvb, offset, 16, (const guint8 *) &addr);
5851             proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+16, 2, port);
5852
5853             } else { /* we have 1 Byte MS/TP Address or anything else interpreted as an address */
5854                 tmp = tvb_bytes_to_str(tvb, offset, lvt);
5855                 ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s", tmp);
5856             }
5857         }
5858         offset += lvt;
5859     }
5860
5861     if (ti)
5862         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5863
5864     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
5865
5866     return offset;
5867 }
5868
5869 static guint
5870 fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5871 {
5872     guint8  tag_no, tag_info;
5873     guint32 lvt;
5874     guint   offs;
5875
5876     offset = fUnsignedTag(tvb, pinfo, tree, offset, "network-number");
5877     offs   = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5878     if (lvt == 0) {
5879         proto_tree_add_text(tree, tvb, offset, offs, "MAC-address: broadcast");
5880         offset += offs;
5881     } else
5882         offset  = fMacAddress(tvb, pinfo, tree, offset, "MAC-address: ", lvt);
5883
5884     return offset;
5885 }
5886
5887 static guint
5888 fSessionKey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5889 {
5890     offset = fOctetString(tvb, pinfo, tree, offset, "session key: ", 8);
5891     return fAddress(tvb, pinfo, tree, offset);
5892 }
5893
5894 static guint
5895 fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5896 {
5897     guint8      tag_no, tag_info;
5898     guint32     lvt;
5899     guint       tag_length;
5900     proto_item *ti;
5901     proto_tree *subtree;
5902     guint32     object_id;
5903
5904     tag_length  = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5905     object_id   = tvb_get_ntohl(tvb, offset+tag_length);
5906     object_type = object_id_type(object_id);
5907     ti = proto_tree_add_text(tree, tvb, offset, tag_length + 4,
5908         "ObjectIdentifier: %s, %u",
5909         val_to_split_str(object_type,
5910             128,
5911             BACnetObjectType,
5912             ASHRAE_Reserved_Fmt,
5913             Vendor_Proprietary_Fmt),
5914         object_id_instance(object_id));
5915     if (col_get_writable(pinfo->cinfo))
5916         col_append_fstr(pinfo->cinfo, COL_INFO, "%s,%u ",
5917             val_to_split_str(object_type,
5918                 128,
5919                 BACnetObjectType,
5920                 ASHRAE_Reserved_Fmt,
5921                 Vendor_Proprietary_Fmt),
5922                 object_id_instance(object_id));
5923
5924     /* update BACnet Statistics */
5925     updateBacnetInfoValue(BACINFO_OBJECTID,
5926                   wmem_strdup(wmem_packet_scope(),
5927                     val_to_split_str(object_type, 128,
5928                     BACnetObjectType, ASHRAE_Reserved_Fmt,
5929                     Vendor_Proprietary_Fmt)));
5930     updateBacnetInfoValue(BACINFO_INSTANCEID,
5931                   wmem_strdup_printf(wmem_packet_scope(),
5932                     "Instance ID: %u",
5933                     object_id_instance(object_id)));
5934
5935     /* here are the details of how we arrived at the above text */
5936     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5937     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5938     offset += tag_length;
5939     proto_tree_add_item(subtree, hf_bacapp_objectType, tvb, offset, 4, ENC_BIG_ENDIAN);
5940     proto_tree_add_item(subtree, hf_bacapp_instanceNumber, tvb, offset, 4, ENC_BIG_ENDIAN);
5941     offset += 4;
5942
5943     return offset;
5944 }
5945
5946 static guint
5947 fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5948 {
5949     guint8  tag_no, tag_info;
5950     guint32 lvt;
5951
5952     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5953     if (tag_no < 2) {
5954         if (tag_no == 0) { /* device */
5955             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
5956         }
5957         else {  /* address */
5958             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5959             offset  = fAddress(tvb, pinfo, tree, offset);
5960             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5961         }
5962     }
5963     return offset;
5964 }
5965
5966 static guint
5967 fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5968 {
5969     guint       lastoffset = 0;
5970     guint8      tag_no, tag_info;
5971     guint32     lvt;
5972     proto_tree *orgtree    = tree;
5973     proto_item *tt;
5974     proto_tree *subtree;
5975
5976     /* beginning of new item - indent and label */
5977     tt   = proto_tree_add_text(orgtree, tvb, offset, 1, "Recipient Process" );
5978     tree = proto_item_add_subtree(tt, ett_bacapp_value);
5979
5980     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
5981         lastoffset = offset;
5982
5983         switch (fTagNo(tvb, offset)) {
5984         case 0: /* recipient */
5985             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
5986             tt = proto_tree_add_text(tree, tvb, offset, 1, "Recipient");    /* add tree label and indent */
5987             subtree = proto_item_add_subtree(tt, ett_bacapp_value);
5988             offset  = fRecipient(tvb, pinfo, subtree, offset);
5989             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
5990             break;
5991         case 1: /* processId */
5992             offset = fProcessId(tvb, pinfo, tree, offset);
5993             lastoffset = offset;
5994             break;
5995         default:
5996             break;
5997         }
5998         if (offset == lastoffset) break;     /* nothing happened, exit loop */
5999     }
6000     return offset;
6001 }
6002
6003 static guint
6004 fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6005 {
6006     guint       lastoffset = 0;
6007     guint8      tag_no, tag_info;
6008     guint32     lvt;
6009     proto_tree *subtree;
6010     proto_item *tt;
6011     proto_tree *orgtree    = tree;
6012     guint       itemno     = 1;
6013
6014     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6015         lastoffset = offset;
6016         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6017         if (tag_is_closing(tag_info) ) {
6018             return offset;
6019         }
6020         switch (tag_no) {
6021
6022         case 0: /* recipient */
6023                 /* beginning of new item in list */
6024                 tt = proto_tree_add_text(orgtree, tvb, offset, 1, "Subscription %d",itemno);    /* add tree label and indent */
6025                 itemno = itemno + 1;
6026                 tree = proto_item_add_subtree(tt, ett_bacapp_value);
6027
6028                 tt = proto_tree_add_text(tree, tvb, offset, 1, "Recipient");    /* add tree label and indent */
6029                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
6030                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
6031                 offset  = fRecipientProcess(tvb, pinfo, subtree, offset);
6032                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);  /* show context close */
6033             break;
6034         case 1: /* MonitoredPropertyReference */
6035                 tt = proto_tree_add_text(tree, tvb, offset, 1, "Monitored Property Reference");
6036                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
6037                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6038                 offset  = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
6039                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6040             break;
6041         case 2: /* IssueConfirmedNotifications - boolean */
6042             offset = fBooleanTag(tvb, pinfo, tree, offset, "Issue Confirmed Notifications: ");
6043             break;
6044         case 3: /* TimeRemaining */
6045             offset = fUnsignedTag(tvb, pinfo, tree, offset, "Time Remaining: ");
6046             break;
6047         case 4: /* COVIncrement */
6048             offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
6049             break;
6050         default:
6051             break;
6052         }
6053         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6054     }
6055     return offset;
6056 }
6057
6058 static guint
6059 fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6060 {
6061     offset = fObjectIdentifier(tvb, pinfo, tree, offset);
6062     return fAddress(tvb, pinfo, tree, offset);
6063 }
6064
6065 static guint
6066 fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match)
6067 {
6068     guint       lastoffset = 0, len;
6069     guint8      tag_no, tag_info;
6070     guint32     lvt;
6071     proto_tree *subtree    = tree;
6072
6073     /* set the optional global properties to indicate not-used */
6074     propertyArrayIndex = -1;
6075     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6076         lastoffset = offset;
6077         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6078         if (tag_is_closing(tag_info) ) {
6079             if (tag_no == tag_match) {
6080                 return offset;
6081             }
6082             offset += len;
6083             subtree = tree;
6084             continue;
6085         }
6086         switch (tag_no) {
6087
6088         case 0: /* deviceIdentifier */
6089             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
6090             break;
6091         case 1: /* objectIdentifier */
6092             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
6093             break;
6094         case 2: /* propertyIdentifier */
6095             offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
6096             break;
6097         case 3: /* propertyArrayIndex */
6098             offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
6099             break;
6100         case 4: /* propertyValue */
6101             offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
6102             break;
6103         case 5: /* priority */
6104             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
6105             break;
6106         case 6: /* postDelay */
6107             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Post Delay: ");
6108             break;
6109         case 7: /* quitOnFailure */
6110             offset = fBooleanTag(tvb, pinfo, subtree, offset,
6111                 "Quit On Failure: ");
6112             break;
6113         case 8: /* writeSuccessful */
6114             offset = fBooleanTag(tvb, pinfo, subtree, offset,
6115                 "Write Successful: ");
6116             break;
6117         default:
6118             return offset;
6119         }
6120         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6121     }
6122     return offset;
6123 }
6124
6125 /* BACnetActionList ::= SEQUENCE{
6126       action [0] SEQUENCE OF BACnetActionCommand
6127       }
6128 */
6129 static guint
6130 fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6131 {
6132     guint       lastoffset = 0, len;
6133     guint8      tag_no, tag_info;
6134     guint32     lvt;
6135     proto_tree *subtree    = tree;
6136     proto_item *ti;
6137
6138     while (tvb_reported_length_remaining(tvb, offset) > 0) {
6139         lastoffset = offset;
6140         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6141         if (tag_is_closing(tag_info)) {
6142             subtree = tree;
6143             if ( tag_no != 0 ) /* don't eat the closing property tag, just return */
6144                 return offset;
6145             offset += len;
6146             continue;
6147         }
6148         if (tag_is_opening(tag_info)) {
6149             ti = proto_tree_add_text(tree, tvb, offset, 1, "Action List");
6150             subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6151             offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
6152                 &tag_no, &tag_info, &lvt);
6153         }
6154         switch (tag_no) {
6155         case 0: /* BACnetActionCommand */
6156             offset = fActionCommand(tvb, pinfo, subtree, offset, tag_no);
6157             break;
6158         default:
6159             break;
6160         }
6161         if (offset == lastoffset) break;    /* nothing happened, exit loop */
6162     }
6163     return offset;
6164 }
6165
6166 static guint
6167 fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6168 {
6169     guint8       tag_no, tag_info;
6170     guint32      lvt;
6171     guint        tag_len;
6172     proto_item  *ti;
6173     proto_tree  *subtree;
6174     const gchar *label = "Property Identifier";
6175
6176     propertyIdentifier = 0; /* global Variable */
6177     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6178     /* can we decode this value? */
6179     if (fUnsigned32(tvb, offset+tag_len, lvt, (guint32 *)&propertyIdentifier)) {
6180         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
6181             "%s: %s (%u)", label,
6182             val_to_split_str(propertyIdentifier, 512,
6183                 BACnetPropertyIdentifier,
6184                 ASHRAE_Reserved_Fmt,
6185                 Vendor_Proprietary_Fmt), propertyIdentifier);
6186         if (col_get_writable(pinfo->cinfo))
6187             col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
6188                 val_to_split_str(propertyIdentifier, 512,
6189                     BACnetPropertyIdentifier,
6190                     ASHRAE_Reserved_Fmt,
6191                     Vendor_Proprietary_Fmt));
6192     } else {
6193         /* property identifiers cannot be larger than 22-bits */
6194         return offset;
6195     }
6196     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6197     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6198     proto_tree_add_item(subtree, hf_BACnetPropertyIdentifier, tvb,
6199         offset+tag_len, lvt, ENC_BIG_ENDIAN);
6200
6201     return offset+tag_len+lvt;
6202 }
6203
6204 static guint
6205 fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6206 {
6207     guint8      tag_no, tag_info;
6208     guint32     lvt;
6209     guint       tag_len;
6210     proto_item *ti;
6211     proto_tree *subtree;
6212
6213     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6214     if (fUnsigned32(tvb, offset + tag_len, lvt, (guint32 *)&propertyArrayIndex))
6215         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
6216             "property Array Index (Unsigned) %u", propertyArrayIndex);
6217     else
6218         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
6219             "property Array Index - %u octets (Unsigned)", lvt);
6220     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6221     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6222
6223     return offset+tag_len+lvt;
6224 }
6225
6226 static guint
6227 fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6228 {
6229     guint8      tag_no, tag_info, character_set;
6230     guint32     lvt, l;
6231     gsize       inbytesleft, outbytesleft = 512;
6232     guint       offs, extra = 1;
6233     guint8     *str_val;
6234     const char *coding;
6235     guint8      bf_arr[512], *out = &bf_arr[0];
6236     proto_item *ti;
6237     proto_tree *subtree;
6238     guint       start = offset;
6239
6240     if (tvb_reported_length_remaining(tvb, offset) > 0) {
6241
6242         offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6243
6244         character_set = tvb_get_guint8(tvb, offset+offs);
6245         /* Account for code page if DBCS */
6246         if (character_set == 1) {
6247             extra = 3;
6248         }
6249         offset += (offs+extra);
6250         lvt -= (extra);
6251
6252         do {
6253             inbytesleft = l = MIN(lvt, 256);
6254             /*
6255              * XXX - are we guaranteed that these encoding
6256              * names correspond, on *all* platforms with
6257              * iconv(), to the encodings we want?
6258              * If not (and perhaps even if so), we should
6259              * perhaps have our own iconv() implementation,
6260              * with a different name, so that we control the
6261              * encodings it supports and the names of those
6262              * encodings.
6263              *
6264              * We should also handle that in the general
6265              * string handling code, rather than making it
6266              * specific to the BACAPP dissector, as many
6267              * other dissectors need to handle various
6268              * character encodings.
6269              */
6270             str_val = tvb_get_string(wmem_packet_scope(), tvb, offset, l);
6271             /** this decoding may be not correct for multi-byte characters, Lka */
6272             switch (character_set) {
6273             case ANSI_X34:
6274                 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UTF-8");
6275                 coding = "UTF-8";
6276                 break;
6277             case IBM_MS_DBCS:
6278                 out = str_val;
6279                 coding = "IBM MS DBCS";
6280                 break;
6281             case JIS_C_6226:
6282                 out = str_val;
6283                 coding = "JIS C 6226";
6284                 break;
6285             case ISO_10646_UCS4:
6286                 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-4BE");
6287                 coding = "ISO 10646 UCS-4";
6288                 break;
6289             case ISO_10646_UCS2:
6290                 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-2BE");
6291                 coding = "ISO 10646 UCS-2";
6292                 break;
6293             case ISO_18859_1:
6294                 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "ISO8859-1");
6295                 coding = "ISO 8859-1";
6296                 break;
6297             default:
6298                 out = str_val;
6299                 coding = "unknown";
6300                 break;
6301             }
6302             ti = proto_tree_add_text(tree, tvb, offset, l, "%s%s '%s'", label, coding, out);
6303             lvt    -= l;
6304             offset += l;
6305         } while (lvt > 0);
6306
6307         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6308
6309         fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6310         proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, ENC_BIG_ENDIAN);
6311
6312         if (character_set == 1) {
6313             proto_tree_add_text(subtree, tvb, start+offs+1, 2, "Code Page: %d", tvb_get_ntohs(tvb, start+offs+1));
6314         }
6315         /* XXX - put the string value here */
6316     }
6317     return offset;
6318 }
6319
6320 static guint
6321 fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label,
6322     const value_string *src)
6323 {
6324     guint8      tag_no, tag_info, tmp;
6325     gint        j, unused, skip;
6326     guint       start = offset;
6327     guint       offs;
6328     guint32     lvt, i, numberOfBytes;
6329     guint8      bf_arr[256];
6330     proto_tree* subtree = tree;
6331     proto_item* ti;
6332
6333     offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6334     numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
6335     offset += offs;
6336     unused  = tvb_get_guint8(tvb, offset); /* get the unused Bits */
6337     ti      = proto_tree_add_text(tree, tvb, start, offs+lvt,
6338                                   "%s(Bit String)", label);
6339     if (ti) {
6340         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6341     }
6342     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6343     proto_tree_add_text(subtree, tvb, offset, 1,
6344                 "Unused bits: %u", unused);
6345     skip = 0;
6346     for (i = 0; i < numberOfBytes; i++) {
6347         tmp = tvb_get_guint8(tvb, (offset)+i+1);
6348         if (i == numberOfBytes-1) { skip = unused; }
6349         for (j = 0; j < 8-skip; j++) {
6350             if (src != NULL) {
6351                 if (tmp & (1 << (7 - j)))
6352                     proto_tree_add_text(subtree, tvb,
6353                         offset+i+1, 1,
6354                         "%s = TRUE",
6355                         val_to_str((guint) (i*8 +j),
6356                             src,
6357                             ASHRAE_Reserved_Fmt));
6358                 else
6359                     proto_tree_add_text(subtree, tvb,
6360                         offset+i+1, 1,
6361                         "%s = FALSE",
6362                         val_to_str((guint) (i*8 +j),
6363                             src,
6364                             ASHRAE_Reserved_Fmt));
6365             } else {
6366                 bf_arr[MIN(255, (i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
6367             }
6368         }
6369     }
6370
6371     if (src == NULL) {
6372         bf_arr[MIN(255, numberOfBytes*8-unused)] = 0;
6373         proto_tree_add_text(subtree, tvb, offset, lvt, "B'%s'", bf_arr);
6374     }
6375
6376     offset += lvt;
6377
6378     return offset;
6379 }
6380
6381 static guint
6382 fBitStringTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6383 {
6384     return fBitStringTagVS(tvb, pinfo, tree, offset, label, NULL);
6385 }
6386
6387 /* handles generic application types, as well as enumerated and enumerations
6388    with reserved and proprietarty ranges (split) */
6389 static guint
6390 fApplicationTypesEnumeratedSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
6391     const gchar *label, const value_string *src, guint32 split_val)
6392 {
6393     guint8  tag_no, tag_info;
6394     guint32 lvt;
6395     guint   tag_len;
6396
6397     if (tvb_reported_length_remaining(tvb, offset) > 0) {
6398
6399         tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6400         if (!tag_is_context_specific(tag_info)) {
6401             switch (tag_no) {
6402             case 0: /** NULL 20.2.2 */
6403                 offset = fNullTag(tvb, pinfo, tree, offset, label);
6404                 break;
6405             case 1: /** BOOLEAN 20.2.3 */
6406                 offset = fBooleanTag(tvb, pinfo, tree, offset, label);
6407                 break;
6408             case 2: /** Unsigned Integer 20.2.4 */
6409                 offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
6410                 break;
6411             case 3: /** Signed Integer 20.2.5 */
6412                 offset = fSignedTag(tvb, pinfo, tree, offset, label);
6413                 break;
6414             case 4: /** Real 20.2.6 */
6415                 offset = fRealTag(tvb, pinfo, tree, offset, label);
6416                 break;
6417             case 5: /** Double 20.2.7 */
6418                 offset = fDoubleTag(tvb, pinfo, tree, offset, label);
6419                 break;
6420             case 6: /** Octet String 20.2.8 */
6421                 offset = fOctetString(tvb, pinfo, tree, offset, label, lvt);
6422                 break;
6423             case 7: /** Character String 20.2.9 */
6424                 offset = fCharacterString(tvb, pinfo, tree, offset, label);
6425                 break;
6426             case 8: /** Bit String 20.2.10 */
6427                 offset = fBitStringTagVS(tvb, pinfo, tree, offset, label, src);
6428                 break;
6429             case 9: /** Enumerated 20.2.11 */
6430                 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, src, split_val);
6431                 break;
6432             case 10: /** Date 20.2.12 */
6433                 offset = fDate(tvb, pinfo, tree, offset, label);
6434                 break;
6435             case 11: /** Time 20.2.13 */
6436                 offset = fTime(tvb, pinfo, tree, offset, label);
6437                 break;
6438             case 12: /** BACnetObjectIdentifier 20.2.14 */
6439                 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
6440                 break;
6441             case 13: /* reserved for ASHRAE */
6442             case 14:
6443             case 15:
6444                 proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s'reserved for ASHRAE'", label);
6445                 offset += lvt + tag_len;
6446                 break;
6447             default:
6448                 break;
6449             }
6450
6451         }
6452     }
6453     return offset;
6454 }
6455
6456 static guint
6457 fShedLevel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6458 {
6459     guint lastoffset = 0;
6460
6461     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6462         lastoffset = offset;
6463
6464         switch (fTagNo(tvb, offset)) {
6465         case 0: /* percent */
6466             offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed percent: ");
6467             break;
6468         case 1: /* level */
6469             offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed level: ");
6470             break;
6471         case 2: /* amount */
6472             offset = fRealTag(tvb, pinfo, tree, offset, "shed amount: ");
6473             break;
6474         default:
6475             return offset;
6476         }
6477         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6478     }
6479     return offset;
6480 }
6481
6482 static guint
6483 fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
6484     const gchar *label, const value_string *vs)
6485 {
6486     return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, vs, 0);
6487 }
6488
6489 static guint
6490 fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
6491     const gchar *label)
6492 {
6493     return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, NULL, 0);
6494 }
6495
6496 static guint
6497 fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6498 {
6499     guint8      tag_no, tag_info;
6500     guint32     lvt;
6501     guint       tag_len;
6502     proto_item *ti;
6503     proto_tree *subtree;
6504     gint        tvb_len;
6505
6506     (void)label;
6507     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6508     /* cap the the suggested length in case of bad data */
6509     tvb_len = tvb_reported_length_remaining(tvb, offset+tag_len);
6510     if ((tvb_len >= 0) && ((guint32)tvb_len < lvt)) {
6511         lvt = tvb_len;
6512     }
6513     ti = proto_tree_add_text(tree, tvb, offset+tag_len, lvt,
6514         "Context Value (as %u DATA octets)", lvt);
6515
6516     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6517     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6518
6519     return offset + tag_len + lvt;
6520 }
6521 /*
6522 BACnetPrescale ::= SEQUENCE {
6523     multiplier  [0] Unsigned,
6524 moduloDivide    [1] Unsigned
6525 }
6526 */
6527 static guint
6528 fPrescale(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
6529 {
6530     guint8  tag_no, tag_info;
6531     guint32 lvt;
6532     guint   lastoffset = 0;
6533
6534     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6535         lastoffset = offset;
6536         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6537         if (tag_is_closing(tag_info) ) {
6538             return offset;
6539             }
6540         switch (tag_no) {
6541         case 0: /* multiplier */
6542             offset = fUnsignedTag(tvb, pinfo, tree, offset, "Multiplier: ");
6543             break;
6544         case 1: /* moduloDivide */
6545             offset = fUnsignedTag(tvb, pinfo, tree, offset, "Modulo Divide: ");
6546             break;
6547         default:
6548             return offset;
6549         }
6550         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6551     }
6552     return offset;
6553
6554 }
6555 /*
6556 BACnetScale ::= CHOICE {
6557     floatScale  [0] REAL,
6558 integerScale    [1] INTEGER
6559 }
6560 */
6561 static guint
6562 fScale(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
6563 {
6564     guint8  tag_no, tag_info;
6565     guint32 lvt;
6566     guint   lastoffset = 0;
6567
6568     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6569         lastoffset = offset;
6570         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6571         if (tag_is_closing(tag_info) ) {
6572             return offset;
6573             }
6574         switch (tag_no) {
6575         case 0: /* floatScale */
6576             offset = fRealTag(tvb, pinfo, tree, offset, "Float Scale: ");
6577             break;
6578         case 1: /* integerScale */
6579             offset = fSignedTag(tvb, pinfo, tree, offset, "Integer Scale: ");
6580             break;
6581         default:
6582             return offset;
6583         }
6584         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6585     }
6586     return offset;
6587 }
6588 /*
6589 BACnetAccumulatorRecord ::= SEQUENCE {
6590     timestamp       [0] BACnetDateTime,
6591     presentValue        [1] Unsigned,
6592     accumulatedValue    [2] Unsigned,
6593     accumulatortStatus  [3] ENUMERATED {
6594                     normal          (0),
6595                     starting        (1),
6596                     recovered       (2),
6597                     abnormal        (3),
6598                     failed          (4)
6599                     }
6600 }
6601 */
6602 static guint
6603 fLoggingRecord(tvbuff_t *tvb, packet_info *pinfo  _U_, proto_tree *tree, guint offset)
6604 {
6605     guint8  tag_no, tag_info;
6606     guint32 lvt;
6607     guint   lastoffset = 0;
6608
6609     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6610         lastoffset = offset;
6611         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6612         if (tag_is_closing(tag_info) ) {
6613             return offset;
6614             }
6615         switch (tag_no) {
6616         case 0: /* timestamp */
6617             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6618             offset  = fDateTime(tvb, pinfo, tree, offset, "Timestamp: ");
6619             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6620             break;
6621         case 1: /* presentValue */
6622             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Present Value: ");
6623             break;
6624         case 2: /* accumulatedValue */
6625             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Accumulated Value: ");
6626             break;
6627         case 3: /* accumulatorStatus */
6628             offset  = fEnumeratedTag(tvb, pinfo, tree, offset, "Accumulator Status: ", BACnetAccumulatorStatus);
6629             break;
6630         default:
6631             return offset;
6632         }
6633         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6634     }
6635     return offset;
6636 }
6637
6638 /*
6639  SEQ OF Any enumeration (current usage is SEQ OF BACnetDoorAlarmState
6640 */
6641 static guint
6642 fSequenceOfEnums(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, const value_string *vs)
6643 {
6644     guint8  tag_no, tag_info;
6645     guint32 lvt;
6646     guint   lastoffset = 0;
6647
6648     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6649         lastoffset = offset;
6650         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6651         if (tag_is_closing(tag_info) ) {
6652             return offset;
6653             }
6654         offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, label, vs);
6655         if ( offset == lastoffset ) break;
6656     }
6657     return offset;
6658 }
6659
6660 /*
6661 SEQ OF BACnetDeviceObjectReference (accessed as an array)
6662 }
6663 */
6664 static guint
6665 fDoorMembers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6666 {
6667     guint8  tag_no, tag_info;
6668     guint32 lvt;
6669     guint   lastoffset = 0;
6670
6671     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6672         lastoffset = offset;
6673         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6674         if (tag_is_closing(tag_info) ) {
6675             return offset;
6676             }
6677         offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
6678         if (offset == lastoffset) break;
6679     }
6680     return offset;
6681 }
6682
6683 /*
6684 SEQ OF ReadAccessSpecification
6685 */
6686 static guint
6687 fListOfGroupMembers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6688 {
6689     guint8  tag_no, tag_info;
6690     guint32 lvt;
6691     guint   lastoffset = 0;
6692
6693     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6694         lastoffset = offset;
6695         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6696         if (tag_is_closing(tag_info) ) {
6697             return offset;
6698             }
6699         offset = fReadAccessSpecification(tvb, pinfo, tree, offset);
6700         if ( offset == lastoffset ) break;
6701     }
6702     return offset;
6703 }
6704
6705 static guint
6706 fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6707 {
6708     guint8  tag_no, tag_info;
6709     guint32 lvt;
6710     guint   lastoffset = 0, depth = 0;
6711     char    ar[256];
6712     guint32 save_object_type;
6713
6714     if (propertyIdentifier >= 0) {
6715         g_snprintf(ar, sizeof(ar), "%s: ",
6716             val_to_split_str(propertyIdentifier, 512,
6717                 BACnetPropertyIdentifier,
6718                 ASHRAE_Reserved_Fmt,
6719                 Vendor_Proprietary_Fmt));
6720     } else {
6721         g_snprintf(ar, sizeof(ar), "Abstract Type: ");
6722     }
6723     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6724         lastoffset = offset;
6725         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6726         if (tag_is_closing(tag_info)) { /* closing tag, but not for me */
6727             if (depth <= 0) return offset;
6728         }
6729
6730         /* Application Tags */
6731         switch (propertyIdentifier) {
6732         case 2: /* action */
6733             /* loop object is application tagged,
6734                 command object is context tagged */
6735             if (tag_is_context_specific(tag_info)) {
6736                 /* BACnetActionList */
6737                 offset = fActionList(tvb, pinfo, tree, offset);
6738             } else {
6739                 /* BACnetAction */
6740                 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6741                     BACnetAction);
6742             }
6743             break;
6744         case 30: /* BACnetAddressBinding */
6745             offset = fAddressBinding(tvb, pinfo, tree, offset);
6746             break;
6747         case 54: /* list of object property reference */
6748             offset = fLOPR(tvb, pinfo, tree, offset);
6749             break;
6750         case 55: /* list-of-session-keys */
6751             fSessionKey(tvb, pinfo, tree, offset);
6752             break;
6753         case 79: /* object-type */
6754         case 96: /* protocol-object-types-supported */
6755             offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar,
6756                 BACnetObjectType, 128);
6757             break;
6758         case 97: /* Protocol-Services-Supported */
6759             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6760                 BACnetServicesSupported);
6761             break;
6762         case 102: /* recipient-list */
6763             offset = fDestination(tvb, pinfo, tree, offset);
6764             break;
6765         case 107: /* segmentation-supported */
6766             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6767                 BACnetSegmentation);
6768             break;
6769         case 111: /* Status-Flags */
6770             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6771                 BACnetStatusFlags);
6772             break;
6773         case 112: /* System-Status */
6774             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6775                 BACnetDeviceStatus);
6776             break;
6777         case 117: /* units */
6778             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6779                 BACnetEngineeringUnits);
6780             break;
6781         case 87:    /* priority-array -- accessed as a BACnetARRAY */
6782             if (propertyArrayIndex == 0) {
6783                 /* BACnetARRAY index 0 refers to the length
6784                 of the array, not the elements of the array */
6785                 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6786             } else {
6787                 offset = fPriorityArray(tvb, pinfo, tree, offset);
6788             }
6789             break;
6790         case 38:    /* exception-schedule */
6791             if (object_type < 128) {
6792                 if (propertyArrayIndex == 0) {
6793                     /* BACnetARRAY index 0 refers to the length
6794                     of the array, not the elements of the array */
6795                     offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6796                 } else {
6797                     offset = fSpecialEvent(tvb, pinfo, tree, offset);
6798                 }
6799             }
6800             break;
6801         case 19:  /* controlled-variable-reference */
6802         case 60:  /* manipulated-variable-reference */
6803         case 132: /* log-device-object-property */
6804             offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
6805             break;
6806         case 109: /* Setpoint-Reference */
6807             /* setpoint-Reference is actually BACnetSetpointReference which is a SEQ of [0] */
6808             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6809             offset = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
6810             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6811             break;
6812         case 123:   /* weekly-schedule -- accessed as a BACnetARRAY */
6813             if (object_type < 128) {
6814                 if (propertyArrayIndex == 0) {
6815                     /* BACnetARRAY index 0 refers to the length
6816                     of the array, not the elements of the array */
6817                     offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6818                 } else {
6819                     offset = fWeeklySchedule(tvb, pinfo, tree, offset);
6820                 }
6821             }
6822             break;
6823         case 127:   /* client COV increment */
6824             offset = fClientCOV(tvb, pinfo, tree, offset);
6825             break;
6826         case 131:  /* log-buffer */
6827             if ( object_type == 25 )
6828                 offset = fEventLogRecord(tvb, pinfo, tree, offset);
6829             else if ( object_type == 27 )
6830                 offset = fLogMultipleRecord(tvb, pinfo, tree, offset);
6831             else
6832                 offset = fLogRecord(tvb, pinfo, tree, offset);
6833             break;
6834         case 159: /* member-of */
6835         case 165: /* zone-members */
6836             offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
6837             break;
6838         case 196: /* last-restart-reason */
6839             offset = fRestartReason(tvb, pinfo, tree, offset);
6840             break;
6841         case 212: /* actual-shed-level */
6842         case 214: /* expected-shed-level */
6843         case 218: /* requested-shed-level */
6844             offset = fShedLevel(tvb, pinfo, tree, offset);
6845             break;
6846         case 152: /* active-cov-subscriptions */
6847             offset = fCOVSubscription(tvb, pinfo, tree, offset);
6848             break;
6849         case 23: /* date-list */
6850             offset = fCalendarEntry(tvb, pinfo, tree, offset);
6851             break;
6852         case 116: /* time-sychronization-recipients */
6853             offset = fRecipient(tvb, pinfo, tree, offset);
6854             break;
6855         case 83: /* event-parameters */
6856             offset = fEventParameter(tvb, pinfo, tree, offset);
6857             break;
6858         case 211: /* subordinate-list */
6859             offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
6860             break;
6861         case 130: /* event-time-stamp */
6862             offset = fEventTimeStamps(tvb, pinfo, tree, offset);
6863             break;
6864         case 197: /* logging-type */
6865             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLoggingType);
6866             break;
6867         case 36: /* event-state */
6868             offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar, BACnetEventState, 64);
6869             break;
6870         case 103: /* reliability */
6871             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetReliability);
6872             break;
6873         case 72: /* notify-type */
6874             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNotifyType);
6875             break;
6876         case 208: /* node-type */
6877             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNodeType);
6878             break;
6879         case 231: /* door-status */
6880             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorStatus);
6881             break;
6882         case 233: /* lock-status */
6883             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLockStatus);
6884             break;
6885         case 235: /* secured-status */
6886             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorSecuredStatus);
6887             break;
6888         case 158: /* maintenance-required */
6889             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetMaintenance);
6890             break;
6891         case 92: /* program-state */
6892             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramState);
6893             break;
6894         case 90: /* program-change */
6895             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramRequest);
6896             break;
6897         case 100: /* reason-for-halt */
6898             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramError);
6899             break;
6900         case 160: /* mode */
6901             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyMode);
6902             break;
6903         case 163: /* silenced */
6904             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetSilencedState);
6905             break;
6906         case 161: /* operation-expected */
6907             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyOperation);
6908             break;
6909         case 164: /* tracking-value */
6910             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
6911             break;
6912         case 41: /* file-access-method */
6913             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetFileAccessMethod);
6914             break;
6915         case 185:  /* prescale */
6916             offset = fPrescale(tvb, pinfo, tree, offset);
6917             break;
6918         case 187:  /* scale */
6919             offset = fScale(tvb, pinfo, tree, offset);
6920             break;
6921         case 184: /* logging-record */
6922             offset = fLoggingRecord(tvb, pinfo, tree, offset);
6923             break;
6924         case 228: /* door-members */
6925             offset = fDoorMembers(tvb, pinfo, tree, offset);
6926             break;
6927         case 181: /* input-reference */
6928             offset = fObjectPropertyReference(tvb, pinfo, tree, offset);
6929             break;
6930         case 78: /* object-property-reference */
6931             offset = fObjectPropertyReference(tvb, pinfo, tree, offset);
6932             break;
6933         case 234: /* masked-alarm-values */
6934             offset = fSequenceOfEnums(tvb, pinfo, tree, offset, "masked-alarm-value: ", BACnetDoorAlarmState);
6935             break;
6936         case 53:    /* list-of-group-members */
6937             save_object_type = object_type;
6938             offset = fListOfGroupMembers(tvb, pinfo, tree, offset);
6939             object_type = save_object_type;
6940             break;
6941         case 85:    /* present-value */
6942             if ( object_type == 11 )    /* group object handling of present-value */
6943             {
6944                 offset = fReadAccessResult(tvb, pinfo, tree, offset);
6945                 break;
6946             }
6947             /* intentially fall through here so don't reorder this case statement */
6948         default:
6949             if (tag_info) {
6950                 if (tag_is_opening(tag_info)) {
6951                     ++depth;
6952                     offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6953                 } else if (tag_is_closing(tag_info)) {
6954                     --depth;
6955                     offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6956                 } else {
6957                     offset  = fContextTaggedValue(tvb, pinfo, tree, offset, ar);
6958                 }
6959             } else {
6960                 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6961             }
6962             break;
6963         }
6964         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6965     }
6966     return offset;
6967
6968 }
6969
6970 static guint
6971 fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_info)
6972 {
6973     guint8  tag_no;
6974     guint32 lvt;
6975
6976     if (tag_is_opening(tag_info)) {
6977         offset += fTagHeaderTree(tvb, pinfo, tree, offset,
6978                                  &tag_no, &tag_info, &lvt);
6979         offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
6980         if (tvb_length_remaining(tvb, offset) > 0) {
6981             offset += fTagHeaderTree(tvb, pinfo, tree, offset,
6982                                      &tag_no, &tag_info, &lvt);
6983         }
6984     } else {
6985         proto_tree_add_text(tree, tvb, offset, tvb_length(tvb) - offset,
6986                             "expected Opening Tag!");
6987         offset = tvb_length(tvb);
6988     }
6989
6990     return offset;
6991 }
6992
6993
6994 static guint
6995 fPropertyIdentifierValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset)
6996 {
6997     guint   lastoffset = offset;
6998     guint8  tag_no, tag_info;
6999     guint32 lvt;
7000
7001     offset = fPropertyReference(tvb, pinfo, tree, offset, tagoffset, 0);
7002     if (offset > lastoffset) {
7003         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7004         if (tag_no == tagoffset+2) {  /* Value - might not be present in ReadAccessResult */
7005             offset = fPropertyValue(tvb, pinfo, tree, offset, tag_info);
7006         }
7007     }
7008     return offset;
7009 }
7010
7011 static guint
7012 fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7013 {
7014     guint   lastoffset = 0;
7015     guint8  tag_no, tag_info;
7016     guint32 lvt;
7017
7018     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7019         lastoffset = offset;
7020         offset = fPropertyIdentifierValue(tvb, pinfo, tree, offset, 0);
7021         if (offset > lastoffset) {
7022             /* detect optional priority
7023             by looking to see if the next tag is context tag number 3 */
7024             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7025             if (tag_is_context_specific(tag_info) && (tag_no == 3))
7026                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
7027         }
7028         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7029     }
7030     return offset;
7031 }
7032
7033 static guint
7034 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7035 {
7036     guint       lastoffset = 0, len;
7037     guint8      tag_no, tag_info;
7038     guint32     lvt;
7039     proto_tree *subtree = tree;
7040     proto_item *tt;
7041
7042     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7043         lastoffset = offset;
7044         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7045         if (tag_is_closing(tag_info)) {
7046             offset += len;
7047             subtree = tree;
7048             continue;
7049         }
7050
7051         switch (tag_no) {
7052         case 0: /* ProcessId */
7053             offset = fUnsignedTag(tvb, pinfo, tree, offset, "subscriber Process Id: ");
7054             break;
7055         case 1: /* monitored ObjectId */
7056             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7057             break;
7058         case 2: /* issueConfirmedNotifications */
7059             offset = fBooleanTag(tvb, pinfo, tree, offset, "issue Confirmed Notifications: ");
7060             break;
7061         case 3: /* life time */
7062             offset = fTimeSpan(tvb, pinfo, tree, offset, "life time");
7063             break;
7064         case 4: /* monitoredPropertyIdentifier */
7065             if (tag_is_opening(tag_info)) {
7066                 tt = proto_tree_add_text(subtree, tvb, offset, 1, "monitoredPropertyIdentifier");
7067                 if (tt) {
7068                     subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7069                 }
7070                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7071                 offset  = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
7072                 break;
7073             }
7074             FAULT;
7075             break;
7076         case 5: /* covIncrement */
7077             offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
7078             break;
7079         default:
7080             return offset;
7081         }
7082         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7083     }
7084     return offset;
7085 }
7086
7087 static guint
7088 fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7089 {
7090     return fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
7091 }
7092
7093 static guint
7094 fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7095 {
7096     guint lastoffset = 0;
7097
7098     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7099         lastoffset = offset;
7100
7101         switch (fTagNo(tvb, offset)) {
7102         case 0: /* deviceInstanceLowLimit */
7103             offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance Low Limit: ");
7104             break;
7105         case 1: /* deviceInstanceHighLimit */
7106             offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance High Limit: ");
7107             break;
7108         case 2: /* BACnetObjectId */
7109             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7110             break;
7111         case 3: /* messageText */
7112             offset = fCharacterString(tvb, pinfo, tree, offset, "Object Name: ");
7113             break;
7114         default:
7115             return offset;
7116         }
7117         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7118     }
7119     return offset;
7120 }
7121
7122
7123 static guint
7124 fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
7125 {
7126     guint   lastoffset = 0;
7127     guint8  tag_no, tag_info;
7128     guint32 lvt;
7129
7130     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7131     if (tag_is_opening(tag_info) && tag_no == 0) {
7132         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* opening context tag 0 */
7133         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7134             lastoffset = offset;
7135             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7136             if (tag_is_closing(tag_info)) {
7137                 /* should be closing context tag 0 */
7138                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7139                 return offset;
7140             }
7141
7142             offset = fTimeValue(tvb, pinfo, subtree, offset);
7143             if (offset == lastoffset) break;    /* nothing happened, exit loop */
7144         }
7145     } else if ((tag_no == 0) && (lvt == 0)) {
7146         /* not sure null (empty array element) is legal */
7147         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7148     }
7149     return offset;
7150 }
7151
7152 static guint
7153 fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7154 {
7155     guint       lastoffset = 0;
7156     guint8      tag_no, tag_info;
7157     guint32     lvt;
7158     guint       i = 1; /* day of week array index */
7159     proto_tree *subtree = tree;
7160     proto_item *tt;
7161
7162     if (propertyArrayIndex > 0) {
7163         /* BACnetARRAY index 0 refers to the length
7164         of the array, not the elements of the array.
7165         BACnetARRAY index -1 is our internal flag that
7166         the optional index was not used.
7167         BACnetARRAY refers to this as all elements of the array.
7168         If the optional index is specified for a BACnetARRAY,
7169         then that specific array element is referenced. */
7170         i = propertyArrayIndex;
7171     }
7172     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7173         lastoffset = offset;
7174         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7175         if (tag_is_closing(tag_info)) {
7176             return offset; /* outer encoding will print out closing tag */
7177         }
7178         tt = proto_tree_add_text(tree, tvb, offset, 0, "%s", val_to_str(i++, day_of_week, "day of week (%d) not found"));
7179         subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7180         offset = fDailySchedule(tvb, pinfo, subtree, offset);
7181         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7182     }
7183     return offset;
7184 }
7185
7186
7187 static guint
7188 fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7189 {
7190     if (tvb_reported_length_remaining(tvb, offset) <= 0)
7191         return offset;
7192
7193     return fDateTime(tvb, pinfo, tree, offset, "UTC-Time: ");
7194 }
7195
7196 static guint
7197 fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7198 {
7199     if (tvb_reported_length_remaining(tvb, offset) <= 0)
7200         return offset;
7201
7202     return fDateTime(tvb, pinfo, tree, offset, NULL);
7203 }
7204
7205 static guint
7206 fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7207 {
7208     if (tvb_reported_length_remaining(tvb, offset) <= 0)
7209         return offset;
7210     offset = fDate(tvb, pinfo, tree, offset, "Start Date: ");
7211     return fDate(tvb, pinfo, tree, offset, "End Date: ");
7212 }
7213
7214 static guint
7215 fVendorIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7216 {
7217     guint32      val   = 0;
7218     guint8       tag_no, tag_info;
7219     guint32      lvt;
7220     guint        tag_len;
7221     proto_item  *ti;
7222     proto_tree  *subtree;
7223     const gchar *label = "Vendor ID";
7224
7225     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7226     if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
7227         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7228             "%s: %s (%u)",
7229             label,
7230             val_to_str_ext_const(val, &BACnetVendorIdentifiers_ext, "Unknown Vendor"),
7231             val);
7232     else
7233         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7234             "%s - %u octets (Unsigned)", label, lvt);
7235     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7236     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7237
7238     if ((lvt < 1) || (lvt > 2)) { /* vendorIDs >= 1  and <= 2 are supported */
7239         proto_tree_add_expert_format(tree, pinfo, &ei_bacapp_bad_length, tvb, 0, lvt,
7240                                 "Wrong length indicated. Expected 1 or 2, got %u", lvt);
7241         return offset+tag_len+lvt;
7242     }
7243
7244     proto_tree_add_item(subtree, hf_BACnetVendorIdentifier, tvb,
7245         offset+tag_len, lvt, ENC_BIG_ENDIAN);
7246
7247     return offset+tag_len+lvt;
7248 }
7249
7250 static guint
7251 fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7252 {
7253     guint32      val   = 0;
7254     guint8       tag_no, tag_info;
7255     guint32      lvt;
7256     guint        tag_len;
7257     proto_item  *ti;
7258     proto_tree  *subtree;
7259     const gchar *label = "Restart Reason";
7260
7261     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7262     if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
7263         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7264             "%s: %s (%u)", label,
7265             val_to_str_const(val, BACnetRestartReason, "Unknown reason"), val);
7266     else
7267         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7268             "%s - %u octets (Unsigned)", label, lvt);
7269     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7270     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7271
7272     if (lvt != 1) {
7273         proto_tree_add_expert_format(tree, pinfo, &ei_bacapp_bad_length, tvb, 0, lvt,
7274                                 "Wrong length indicated. Expected 1, got %u", lvt);
7275         return offset+tag_len+lvt;
7276     }
7277
7278     proto_tree_add_item(subtree, hf_BACnetRestartReason, tvb,
7279         offset+tag_len, lvt, ENC_BIG_ENDIAN);
7280
7281     return offset+tag_len+lvt;
7282 }
7283
7284 static guint
7285 fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7286 {
7287     guint lastoffset = 0;
7288
7289     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7290         lastoffset = offset;
7291         switch (fTagNo(tvb, offset)) {
7292
7293         case 0: /* textMessageSourceDevice */
7294             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7295             break;
7296         case 1: /* messageClass */
7297             switch (fTagNo(tvb, offset)) {
7298             case 0: /* numeric */
7299                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "message Class: ");
7300                 break;
7301             case 1: /* character */
7302                 offset = fCharacterString(tvb, pinfo, tree, offset, "message Class: ");
7303                 break;
7304             }
7305             break;
7306         case 2: /* messagePriority */
7307             offset = fEnumeratedTag(tvb, pinfo, tree, offset, "message Priority: ",
7308                 BACnetMessagePriority);
7309             break;
7310         case 3: /* message */
7311             offset = fCharacterString(tvb, pinfo, tree, offset, "message: ");
7312             break;
7313         default:
7314             return offset;
7315         }
7316         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7317     }
7318     return offset;
7319 }
7320
7321 static guint
7322 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7323 {
7324     return fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
7325 }
7326
7327 static guint
7328 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7329 {
7330     guint       lastoffset, len;
7331     guint8      tag_no, tag_info;
7332     guint32     lvt;
7333     proto_tree *subtree = tree;
7334     proto_item *tt;
7335     tvbuff_t   *next_tvb;
7336     guint       vendor_identifier = 0;
7337     guint       service_number = 0;
7338
7339     len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7340     fUnsigned32(tvb, offset+len, lvt, &vendor_identifier);
7341     if (col_get_writable(pinfo->cinfo))
7342         col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ", vendor_identifier);
7343     offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
7344
7345     next_tvb = tvb_new_subset_remaining(tvb, offset);
7346     if (dissector_try_uint(bacapp_dissector_table,
7347         vendor_identifier, next_tvb, pinfo, tree)) {
7348         /* we parsed it so skip over length and we are done */
7349         offset += tvb_length(next_tvb);
7350         return offset;
7351     }
7352
7353     /* Not handled by vendor dissector */
7354
7355     /* exit loop if nothing happens inside */
7356     while (tvb_reported_length_remaining(tvb, offset) > 0) {
7357         lastoffset = offset;
7358         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7359         if (tag_is_closing(tag_info)) {
7360             if (tag_no == 2) { /* Make sure it's the expected tag */
7361                 offset += len;
7362                 subtree = tree;
7363                 continue;
7364             } else {
7365                 break; /* End loop if incorrect closing tag */
7366             }
7367         }
7368         switch (tag_no) {
7369
7370             /* vendorID is now parsed above */
7371         case 1: /* serviceNumber */
7372             fUnsigned32(tvb, offset+len, lvt, &service_number);
7373             if (col_get_writable(pinfo->cinfo))
7374                 col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ",   service_number);
7375             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
7376             break;
7377         case 2: /*serviceParameters */
7378             if (tag_is_opening(tag_info)) {
7379                 tt = proto_tree_add_text(subtree, tvb, offset, 1, "service Parameters");
7380                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7381                 propertyIdentifier = -1;
7382                 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
7383                 break;
7384             }
7385             FAULT;
7386             break;
7387         default:
7388             return offset;
7389         }
7390         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7391     }
7392
7393     return offset;
7394 }
7395
7396 static guint
7397 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7398 {
7399     return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
7400 }
7401
7402 static guint
7403 fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7404 {
7405     return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
7406 }
7407
7408 static guint
7409 fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
7410 {
7411     guint       lastoffset = 0;
7412     guint8      tag_no, tag_info;
7413     guint32     lvt;
7414     proto_tree *subtree = tree;
7415     proto_item *tt;
7416
7417     if (label != NULL) {
7418         tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", label);
7419         subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7420     }
7421
7422     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7423         lastoffset = offset;
7424         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7425
7426         switch (tag_no) {
7427         case 0: /* subscriberProcessId */
7428             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "requesting Process Id: ");
7429             break;
7430         case 1: /* requestingSource */
7431             offset = fCharacterString(tvb, pinfo, tree, offset, "requesting Source: ");
7432             break;
7433         case 2: /* request */
7434             offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
7435                 "request: ", BACnetLifeSafetyOperation, 64);
7436             break;
7437         case 3: /* objectId */
7438             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
7439             break;
7440         default:
7441             return offset;
7442         }
7443         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7444     }
7445     return offset;
7446 }
7447
7448 typedef struct _value_string_enum {
7449     const value_string *valstr;
7450 } value_string_enum;
7451
7452 static const value_string_enum
7453 BACnetPropertyStatesEnums[] = {
7454     { NULL },
7455     {BACnetBinaryPV },
7456     {BACnetEventType },
7457     {BACnetPolarity },
7458     {BACnetProgramRequest },
7459     {BACnetProgramState },
7460     {BACnetProgramError },
7461     {BACnetReliability },
7462     {BACnetEventState },
7463     {BACnetDeviceStatus },
7464     {BACnetEngineeringUnits },
7465     { NULL },
7466     {BACnetLifeSafetyMode },
7467     {BACnetLifeSafetyState },
7468     {BACnetRestartReason },
7469     {BACnetDoorAlarmState },
7470     {BACnetAction },
7471     {BACnetDoorSecuredStatus },
7472     {BACnetDoorStatus },
7473     { NULL }, /* {BACnetDoorValue }, */
7474     {BACnetFileAccessMethod },
7475     {BACnetLockStatus },
7476     {BACnetLifeSafetyOperation },
7477     {BACnetMaintenance },
7478     {BACnetNodeType },
7479     {BACnetNotifyType },
7480     { NULL }, /* {BACnetSecurityLevel }, */
7481     {BACnetShedState },
7482     {BACnetSilencedState },
7483     { NULL },
7484     { NULL }, /* {BACnetAccessEvent }, */
7485     { NULL }, /* {BACnetZoneOccupancyState }, */
7486     { NULL }, /* {BACnetAccessCredentialDisableReason }, */
7487     { NULL }, /* {BACnetAccessCredentialDisable }, */
7488     { NULL }, /* {BACnetAuthenticationStatus }, */
7489     { NULL },
7490     { NULL }, /* {BACnetBackupState }, */
7491 };
7492 #define BACnetPropertyStatesEnums_Size 36
7493
7494 static guint
7495 fBACnetPropertyStates(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
7496 {
7497     guint8       tag_no, tag_info;
7498     guint32      lvt;
7499     const gchar* label;
7500
7501     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7502     label = wmem_strdup_printf(wmem_packet_scope(), "%s: ",
7503                                val_to_str_const( tag_no, VALS(BACnetPropertyStates), "Unknown State" ));
7504
7505     switch (tag_no) {
7506     case 0:
7507         offset = fBooleanTag(tvb, pinfo, tree, offset, label);
7508         break;
7509     case 11:
7510         offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
7511         break;
7512     default:
7513         if ( (tag_no > BACnetPropertyStatesEnums_Size) ||
7514             VALS(BACnetPropertyStatesEnums[tag_no].valstr) == NULL)
7515         {
7516             offset = fEnumeratedTag(tvb, pinfo, tree, offset, label, NULL);
7517             /* don't use Abstract type here because it is context tagged and therefore we don't know app type */
7518         }
7519         else
7520         {
7521             offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label,
7522                     VALS(BACnetPropertyStatesEnums[tag_no].valstr), 64);
7523         }
7524         break;
7525     }
7526     return offset;
7527 }
7528
7529
7530 /*
7531 BACnetDeviceObjectPropertyValue ::= SEQUENCE {
7532       deviceIdentifier       [0]      BACnetObjectIdentifier,
7533       objectIdentifier       [1]      BACnetObjectIdentifier,
7534       propertyIdentifier     [2]      BACnetPropertyIdentifier,
7535       arrayIndex             [3]      Unsigned OPTIONAL,
7536       value                  [4]      ABSTRACT-SYNTAX.&Type
7537       }
7538 */
7539 static guint
7540 fDeviceObjectPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7541 {
7542     guint   lastoffset = 0;
7543     guint8  tag_no, tag_info;
7544     guint32 lvt;
7545
7546     while (tvb_reported_length_remaining(tvb, offset) > 0) {
7547         lastoffset = offset;
7548         /* check the tag.  A closing tag means we are done */
7549         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7550         if (tag_is_closing(tag_info)) {
7551             return offset;
7552         }
7553         switch (tag_no) {
7554         case 0: /* deviceIdentifier */
7555             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7556             break;
7557         case 1: /* objectIdentifier */
7558             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7559             break;
7560         case 2: /* propertyIdentifier */
7561             offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
7562             break;
7563         case 3: /* arrayIndex - OPTIONAL */
7564             offset = fUnsignedTag(tvb, pinfo, tree, offset,
7565                 "arrayIndex: ");
7566             break;
7567         case 4: /* value */
7568             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7569             offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
7570             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7571             break;
7572         default:
7573             return offset;
7574         }
7575         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7576     }
7577     return offset;
7578 }
7579
7580 /*
7581 BACnetDeviceObjectPropertyReference ::= SEQUENCE {
7582       objectIdentifier       [0]      BACnetObjectIdentifier,
7583       propertyIdentifier     [1]      BACnetPropertyIdentifier,
7584       propertyArrayIndex     [2]      Unsigned OPTIONAL, -- used only with array datatype
7585                                                                 -- if omitted with an array then
7586                                                                 -- the entire array is referenced
7587       deviceIdentifier       [3]      BACnetObjectIdentifier OPTIONAL
7588       }
7589 */
7590 static guint
7591 fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7592 {
7593     return fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
7594 }
7595
7596 /*
7597 BACnetDeviceObjectPropertyReference ::= SEQUENCE {
7598       objectIdentifier       [0]      BACnetObjectIdentifier,
7599       propertyIdentifier     [1]      BACnetPropertyIdentifier,
7600       propertyArrayIndex     [2]      Unsigned OPTIONAL, -- used only with array datatype
7601                                                                 -- if omitted with an array then
7602                                                                 -- the entire array is referenced
7603       deviceIdentifier       [3]      BACnetObjectIdentifier OPTIONAL
7604       }
7605 */
7606 static guint
7607 fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7608 {
7609     guint   lastoffset = 0;
7610     guint8  tag_no, tag_info;
7611     guint32 lvt;
7612
7613     while (tvb_reported_length_remaining(tvb, offset) > 0) {
7614         lastoffset = offset;
7615         /* check the tag.  A closing tag means we are done */
7616         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7617         if (tag_is_closing(tag_info)) {
7618             return offset;
7619         }
7620         switch (tag_no) {
7621         case 0: /* objectIdentifier */
7622             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7623             break;
7624         case 1: /* propertyIdentifier */
7625             offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
7626             break;
7627         case 2: /* arrayIndex - OPTIONAL */
7628             offset = fUnsignedTag(tvb, pinfo, tree, offset,
7629                 "arrayIndex: ");
7630             break;
7631         case 3: /* deviceIdentifier - OPTIONAL */
7632             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7633             break;
7634         default:
7635             return offset;
7636         }
7637         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7638     }
7639     return offset;
7640 }
7641
7642 static guint
7643 fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7644 {
7645     guint       lastoffset = offset;
7646     guint8      tag_no, tag_info;
7647     guint32     lvt;
7648     proto_tree *subtree = tree;
7649     proto_item *tt;
7650
7651     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7652     tt = proto_tree_add_text(subtree, tvb, offset, 0, "notification parameters (%d) %s",
7653         tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
7654     subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7655     /* Opening tag for parameter choice */
7656     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7657
7658     switch (tag_no) {
7659     case 0: /* change-of-bitstring */
7660         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7661             lastoffset = offset;
7662             switch (fTagNo(tvb, offset)) {
7663             case 0:
7664                 offset = fBitStringTag(tvb, pinfo, subtree, offset,
7665                     "referenced-bitstring: ");
7666                 break;
7667             case 1:
7668                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7669                     "status-flags: ", BACnetStatusFlags);
7670                 lastoffset = offset;
7671                 break;
7672             default:
7673                 break;
7674             }
7675             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7676         }
7677         break;
7678     case 1: /* change-of-state */
7679         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7680             lastoffset = offset;
7681             switch (fTagNo(tvb, offset)) {
7682             case 0:
7683                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7684                 offset  = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
7685                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7686                 break;
7687             case 1:
7688                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7689                     "status-flags: ", BACnetStatusFlags);
7690                 lastoffset = offset;
7691                 break;
7692             default:
7693                 break;
7694             }
7695             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7696         }
7697         break;
7698     case 2: /* change-of-value */
7699         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7700             lastoffset = offset;
7701             switch (fTagNo(tvb, offset)) {
7702             case 0:
7703                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7704                 switch (fTagNo(tvb, offset)) {
7705                 case 0:
7706                     offset = fBitStringTag(tvb, pinfo, subtree, offset,
7707                         "changed-bits: ");
7708                     break;
7709                 case 1:
7710                     offset = fRealTag(tvb, pinfo, subtree, offset,
7711                         "changed-value: ");
7712                     break;
7713                 default:
7714                     break;
7715                 }
7716                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7717                 break;
7718             case 1:
7719                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7720                     "status-flags: ", BACnetStatusFlags);
7721                 lastoffset = offset;
7722                 break;
7723             default:
7724                 break;
7725             }
7726             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7727         }
7728         break;
7729     case 3: /* command-failure */
7730         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7731             lastoffset = offset;
7732             switch (fTagNo(tvb, offset)) {
7733             case 0: /* "command-value: " */
7734                 /* from BACnet Table 13-3,
7735                     Standard Object Property Values Returned in Notifications */
7736                 propertyIdentifier = 85; /* PRESENT_VALUE */
7737                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7738                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
7739                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7740                 break;
7741             case 1:
7742                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7743                     "status-flags: ", BACnetStatusFlags);
7744                 break;
7745             case 2: /* "feedback-value: " */
7746                 propertyIdentifier = 40; /* FEEDBACK_VALUE */
7747                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7748                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
7749                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7750                 lastoffset = offset;
7751                 break;
7752             default:
7753                 break;
7754             }
7755             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7756         }
7757         break;
7758     case 4: /* floating-limit */
7759         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7760             lastoffset = offset;
7761             switch (fTagNo(tvb, offset)) {
7762             case 0:
7763                 offset = fRealTag(tvb, pinfo, subtree, offset, "reference-value: ");
7764                 break;
7765             case 1:
7766                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7767                     "status-flags: ", BACnetStatusFlags);
7768                 break;
7769             case 2:
7770                 offset = fRealTag(tvb, pinfo, subtree, offset, "setpoint-value: ");
7771                 break;
7772             case 3:
7773                 offset = fRealTag(tvb, pinfo, subtree, offset, "error-limit: ");
7774                 lastoffset = offset;
7775                 break;
7776             default:
7777                 break;
7778             }
7779             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7780         }
7781         break;
7782     case 5: /* out-of-range */
7783         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7784             lastoffset = offset;
7785             switch (fTagNo(tvb, offset)) {
7786             case 0:
7787                 offset = fRealTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
7788                 break;
7789             case 1:
7790                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7791                     "status-flags: ", BACnetStatusFlags);
7792                 break;
7793             case 2:
7794                 offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
7795                 break;
7796             case 3:
7797                 offset = fRealTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
7798                 lastoffset = offset;
7799                 break;
7800             default:
7801                 break;
7802             }
7803             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7804         }
7805         break;
7806     case 6:
7807         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7808             lastoffset = offset;
7809             offset =fBACnetPropertyValue(tvb, pinfo, subtree, offset);
7810             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7811         }
7812         break;
7813     case 7: /* deprecated (was 'buffer-ready', changed and moved to [10]) */
7814         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7815             lastoffset = offset;
7816             switch (fTagNo(tvb, offset)) {
7817             case 0:
7818                 offset = fObjectIdentifier(tvb, pinfo, subtree, offset); /* buffer-device */
7819                 break;
7820             case 1:
7821                 offset = fObjectIdentifier(tvb, pinfo, subtree, offset); /* buffer-object */
7822                 break;
7823             case 2:
7824                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7825                 offset  = fDateTime(tvb, pinfo, subtree, offset, "previous-notification: ");
7826                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7827                 break;
7828             case 3:
7829                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7830                 offset  = fDateTime(tvb, pinfo, subtree, offset, "current-notification: ");
7831                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7832                 lastoffset = offset;
7833                 break;
7834             default:
7835                 break;
7836             }
7837             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7838         }
7839         break;
7840     case 8: /* change-of-life-safety */
7841         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7842             lastoffset = offset;
7843             switch (fTagNo(tvb, offset)) {
7844             case 0:
7845                 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
7846                     "new-state: ", BACnetLifeSafetyState, 256);
7847                 break;
7848             case 1:
7849                 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
7850                     "new-mode: ", BACnetLifeSafetyMode, 256);
7851                 break;
7852             case 2:
7853                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7854                     "status-flags: ", BACnetStatusFlags);
7855                 break;
7856             case 3:
7857                 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
7858                     "operation-expected: ", BACnetLifeSafetyOperation, 64);
7859                 lastoffset = offset;
7860                 break;
7861             default:
7862                 break;
7863             }
7864             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7865         }
7866         break;
7867     case 9: /* extended */
7868         while (tvb_reported_length_remaining(tvb, offset) > 0) {
7869             lastoffset = offset;
7870             switch (fTagNo(tvb, offset)) {
7871             case 0:
7872                 offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
7873                 break;
7874             case 1:
7875                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7876                     "extended-event-type: ");
7877                 break;
7878             case 2: /* parameters */
7879                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7880                 offset  = fApplicationTypes(tvb, pinfo, subtree, offset, "parameters: ");
7881                 offset  = fDeviceObjectPropertyValue(tvb, pinfo, subtree, offset);
7882                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7883                 lastoffset = offset;
7884                 break;
7885             default:
7886                 break;
7887             }
7888             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7889         }
7890         break;
7891     case 10: /* buffer ready */
7892         while (tvb_reported_length_remaining(tvb, offset) > 0) {
7893             lastoffset = offset;
7894             switch (fTagNo(tvb, offset)) {
7895             case 0: /* buffer-property */
7896                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7897                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
7898                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7899                 break;
7900             case 1:
7901                 offset  = fUnsignedTag(tvb, pinfo, subtree, offset,
7902                     "previous-notification: ");
7903                 break;
7904             case 2:
7905                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7906                     "current-notification: ");
7907                 lastoffset = offset;
7908                 break;
7909             default:
7910                 break;
7911             }
7912             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7913         }
7914         break;
7915     case 11: /* unsigned range */
7916         while (tvb_reported_length_remaining(tvb, offset) > 0) {
7917             lastoffset = offset;
7918             switch (fTagNo(tvb, offset)) {
7919             case 0:
7920                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7921                     "exceeding-value: ");
7922                 break;
7923             case 1:
7924                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7925                     "status-flags: ", BACnetStatusFlags);
7926                 break;
7927             case 2:
7928                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7929                     "exceeded-limit: ");
7930                 lastoffset = offset;
7931                 break;
7932             default:
7933                 break;
7934             }
7935             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7936         }
7937         break;
7938         /* 12 reserved */
7939     case 13: /* access-event */
7940         break;
7941     case 14: /* double-out-of-range */
7942         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7943             lastoffset = offset;
7944             switch (fTagNo(tvb, offset)) {
7945             case 0:
7946                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
7947                 break;
7948             case 1:
7949                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7950                     "status-flags: ", BACnetStatusFlags);
7951                 break;
7952             case 2:
7953                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
7954                 break;
7955             case 3:
7956                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
7957                 lastoffset = offset;
7958                 break;
7959             default:
7960                 break;
7961             }
7962             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7963         }
7964         break;
7965     case 15: /* signed-out-of-range */
7966         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7967             lastoffset = offset;
7968             switch (fTagNo(tvb, offset)) {
7969             case 0:
7970                 offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
7971                 break;
7972             case 1:
7973                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7974                     "status-flags: ", BACnetStatusFlags);
7975                 break;
7976             case 2:
7977                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
7978                 break;
7979             case 3:
7980                 offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
7981                 lastoffset = offset;
7982                 break;
7983             default:
7984                 break;
7985             }
7986             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7987         }
7988         break;
7989     case 16: /* unsigned-out-of-range */
7990         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7991             lastoffset = offset;
7992             switch (fTagNo(tvb, offset)) {
7993             case 0:
7994                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
7995                 break;
7996             case 1:
7997                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7998                     "status-flags: ", BACnetStatusFlags);
7999                 break;
8000             case 2:
8001                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8002                 break;
8003             case 3:
8004                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
8005                 lastoffset = offset;
8006                 break;
8007             default:
8008                 break;
8009             }
8010             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8011         }
8012         break;
8013     case 17: /* change-of-characterstring */
8014         break;
8015     case 18: /* change-of-status-flags */
8016         break;
8017         /* todo: add new parameters here ... */
8018     default:
8019         offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
8020         break;
8021     }
8022
8023     /* Closing tag for parameter choice */
8024     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8025
8026     return offset;
8027 }
8028
8029 static guint
8030 fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8031 {
8032     guint       lastoffset = offset;
8033     guint8      tag_no, tag_info;
8034     guint32     lvt;
8035     proto_tree *subtree = tree;
8036     proto_item *tt;
8037
8038     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8039     tt = proto_tree_add_text(subtree, tvb, offset, 0, "event parameters (%d) %s",
8040         tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
8041     subtree = proto_item_add_subtree(tt, ett_bacapp_value);
8042     /* Opening tag for parameter choice */
8043     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8044
8045     switch (tag_no) {
8046     case 0: /* change-of-bitstring */
8047         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8048             lastoffset = offset;
8049             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8050             if (tag_is_closing(tag_info)) {
8051                 break;
8052             }
8053             switch (tag_no) {
8054             case 0:
8055                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8056                 break;
8057             case 1:
8058                 offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
8059                 break;
8060             case 2: /* SEQUENCE OF BIT STRING */
8061                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8062                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8063                     lastoffset = offset;
8064                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8065                     if (tag_is_closing(tag_info)) {
8066                         break;
8067                     }
8068                     offset = fBitStringTag(tvb, pinfo, subtree, offset,
8069                                            "bitstring value: ");
8070                 }
8071                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8072                 break;
8073             default:
8074                 break;
8075             }
8076         }
8077         break;
8078     case 1: /* change-of-state */
8079         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8080             lastoffset = offset;
8081             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8082             if (tag_is_closing(tag_info)) {
8083                 break;
8084             }
8085             switch (tag_no) {
8086             case 0:
8087                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8088                 break;
8089             case 1: /* SEQUENCE OF BACnetPropertyStates */
8090                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8091                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8092                     lastoffset = offset;
8093                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8094                     if (tag_is_closing(tag_info)) {
8095                         break;
8096                     }
8097                     offset = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
8098                 }
8099                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8100                 break;
8101             default:
8102                 break;
8103             }
8104         }
8105         break;
8106     case 2: /* change-of-value */
8107         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8108             lastoffset = offset;
8109             switch (fTagNo(tvb, offset)) {
8110             case 0:
8111                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8112                 break;
8113             case 1: /* don't loop it, it's a CHOICE */
8114                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8115                 switch (fTagNo(tvb, offset)) {
8116                 case 0:
8117                     offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
8118                     break;
8119                 case 1:
8120                     offset = fRealTag(tvb, pinfo, subtree, offset,
8121                                        "referenced Property Increment: ");
8122                     break;
8123                 default:
8124                     break;
8125                 }
8126                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8127                 break;
8128             default:
8129                 break;
8130             }
8131         }
8132         break;
8133     case 3: /* command-failure */
8134         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8135             lastoffset = offset;
8136             tag_no = fTagNo(tvb, offset);
8137             switch (tag_no) {
8138             case 0:
8139                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8140                 break;
8141             case 1:
8142                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8143                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8144                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8145                 break;
8146             default:
8147                 break;
8148             }
8149         }
8150         break;
8151     case 4: /* floating-limit */
8152         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8153             lastoffset = offset;
8154             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8155             if (tag_is_closing(tag_info)) {
8156                 break;
8157             }
8158             switch (tag_no) {
8159             case 0:
8160                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8161                 break;
8162             case 1:
8163                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8164                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8165                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8166                 break;
8167             case 2:
8168                 offset  = fRealTag(tvb, pinfo, subtree, offset, "low diff limit: ");
8169                 break;
8170             case 3:
8171                 offset  = fRealTag(tvb, pinfo, subtree, offset, "high diff limit: ");
8172                 break;
8173             case 4:
8174                 offset  = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
8175                 break;
8176             default:
8177                 break;
8178             }
8179         }
8180         break;
8181     case 5: /* out-of-range */
8182         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8183             lastoffset = offset;
8184             switch (fTagNo(tvb, offset)) {
8185             case 0:
8186                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8187                 break;
8188             case 1:
8189                 offset = fRealTag(tvb, pinfo, subtree, offset, "low limit: ");
8190                 break;
8191             case 2:
8192                 offset = fRealTag(tvb, pinfo, subtree, offset, "high limit: ");
8193                 break;
8194             case 3:
8195                 offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
8196                 break;
8197             default:
8198                 break;
8199             }
8200         }
8201         break;
8202         /*  deprectated
8203             case 6:
8204             offset = fBACnetPropertyValue (tvb, pinfo, tree, offset);
8205             break;
8206         */
8207
8208     case 7: /* buffer-ready */
8209 #if 0
8210         /* deprecated */
8211         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
8212             lastoffset = offset;
8213             switch (fTagNo(tvb, offset)) {
8214             case 0:
8215                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "notification threshold");
8216                 break;
8217             case 1:
8218                 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8219                                        "previous notification count: ");
8220                 break;
8221             default:
8222                 return offset;
8223             }
8224         }
8225 #endif
8226         break;
8227     case 8: /* change-of-life-safety */
8228         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8229             lastoffset = offset;
8230             switch (fTagNo(tvb, offset)) {
8231             case 0:
8232                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8233                 break;
8234             case 1:
8235                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8236                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8237                     lastoffset = offset;
8238                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8239                     if (tag_is_closing(tag_info)) {
8240                         break;
8241                     }
8242                     offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
8243                                                   "life safety alarm value: ", BACnetLifeSafetyState, 256);
8244                 }
8245                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8246                 break;
8247             case 2:
8248                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8249                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8250                     lastoffset = offset;
8251                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8252                     if (tag_is_closing(tag_info)) {
8253                         break;
8254                     }
8255                     offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
8256                                                   "alarm value: ", BACnetLifeSafetyState, 256);
8257                 }
8258                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8259                 break;
8260             case 3:
8261                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8262                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8263                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8264                 break;
8265             default:
8266                 break;
8267             }
8268         }
8269         break;
8270     case 9: /* extended */
8271         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8272             lastoffset = offset;
8273             switch (fTagNo(tvb, offset)) {
8274             case 0:
8275                 offset = fVendorIdentifier(tvb, pinfo, tree, offset);
8276                 break;
8277             case 1:
8278                 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8279                                        "extended-event-type: ");
8280                 break;
8281             case 2: /* parameters */
8282                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8283                 offset  = fApplicationTypes(tvb, pinfo, tree, offset, "parameters: ");
8284                 offset  = fDeviceObjectPropertyValue(tvb, pinfo, tree, offset);
8285                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8286                 lastoffset = offset;
8287                 break;
8288             default:
8289                 break;
8290             }
8291             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8292         }
8293         break;
8294     case 10: /* buffer-ready */
8295         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8296             lastoffset = offset;
8297             switch (fTagNo(tvb, offset)) {
8298             case 0:
8299                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
8300                                        "notification-threshold: ");
8301                 break;
8302             case 1:
8303                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
8304                                        "previous-notification-count: ");
8305                 break;
8306             default:
8307                 break;
8308             }
8309         }
8310         break;
8311     case 11: /* unsigned-range */
8312         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8313             lastoffset = offset;
8314             switch (fTagNo(tvb, offset)) {
8315             case 0:
8316                 offset = fTimeSpan(tvb, pinfo, tree, offset, "Time Delay");
8317                 break;
8318             case 1:
8319                 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8320                                        "low-limit: ");
8321                 break;
8322             case 2:
8323                 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8324                                        "high-limit: ");
8325                 break;
8326             default:
8327                 break;
8328             }
8329         }
8330         break;
8331     case 13: /* access-event */
8332         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8333             lastoffset = offset;
8334             switch (fTagNo(tvb, offset)) {
8335             case 0:
8336                 /* TODO: [0] SEQUENCE OF BACnetAccessEvent */
8337                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8338                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8339                     lastoffset = offset;
8340                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8341                     if (tag_is_closing(tag_info)) {
8342                         break;
8343                     }
8344                     offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
8345                                                   "access event: ", BACnetAccessEvent, 512);
8346                 }
8347                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8348                 break;
8349             case 1:
8350                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8351                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8352                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8353                 break;
8354             default:
8355                 break;
8356             }
8357         }
8358         break;
8359     case 14: /* double-out-of-range */
8360         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8361             lastoffset = offset;
8362             switch (fTagNo(tvb, offset)) {
8363             case 0:
8364                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8365                 break;
8366             case 1:
8367                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "low limit: ");
8368                 break;
8369             case 2:
8370                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "high limit: ");
8371                 break;
8372             case 3:
8373                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
8374                 break;
8375             default:
8376                 break;
8377             }
8378         }
8379         break;
8380     case 15: /* signed-out-of-range */
8381         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8382             lastoffset = offset;
8383             switch (fTagNo(tvb, offset)) {
8384             case 0:
8385                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8386                 break;
8387             case 1:
8388                 offset = fSignedTag(tvb, pinfo, subtree, offset, "low limit: ");
8389                 break;
8390             case 2:
8391                 offset = fSignedTag(tvb, pinfo, subtree, offset, "high limit: ");
8392                 break;
8393             case 3:
8394                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8395                 break;
8396             default:
8397                 break;
8398             }
8399         }
8400         break;
8401     case 16: /* unsigned-out-of-range */
8402         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8403             lastoffset = offset;
8404             switch (fTagNo(tvb, offset)) {
8405             case 0:
8406                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8407                 break;
8408             case 1:
8409                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "low limit: ");
8410                 break;
8411             case 2:
8412                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "high limit: ");
8413                 break;
8414             case 3:
8415                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8416                 break;
8417             default:
8418                 break;
8419             }
8420         }
8421         break;
8422     case 17: /* change-of-characterstring */
8423         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8424             lastoffset = offset;
8425             switch (fTagNo(tvb, offset)) {
8426             case 0:
8427                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8428                 break;
8429             case 1: /* SEQUENCE OF CharacterString */
8430                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8431                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8432                     lastoffset = offset;
8433                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8434                     if (tag_is_closing(tag_info)) {
8435                         break;
8436                     }
8437                     offset  = fCharacterString(tvb, pinfo, tree, offset, "alarm value: ");
8438                 }
8439                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8440                 break;
8441             default:
8442                 break;
8443             }
8444         }
8445         break;
8446     case 18: /* change-of-status-flags */
8447         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8448             lastoffset = offset;
8449             switch (fTagNo(tvb, offset)) {
8450             case 0:
8451                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8452                 break;
8453             case 1:
8454                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8455                     "selected flags: ", BACnetStatusFlags);
8456                 break;
8457             default:
8458                 break;
8459             }
8460         }
8461         break;
8462         /* todo: add new event-parameter cases here */
8463     default:
8464         break;
8465     }
8466
8467     /* Closing tag for parameter choice */
8468     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8469     return offset;
8470 }
8471
8472 static guint
8473 fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8474 {
8475     guint       lastoffset = 0;
8476     guint8      tag_no, tag_info;
8477     guint32     lvt;
8478     proto_tree *subtree = tree;
8479     proto_item *tt;
8480
8481     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8482         lastoffset = offset;
8483         switch (fTagNo(tvb, offset)) {
8484         case 0: /* timestamp */
8485             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8486             offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
8487             offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
8488             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8489             break;
8490         case 1: /* logDatum: don't loop, it's a CHOICE */
8491             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8492             switch (fTagNo(tvb, offset)) {
8493             case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
8494                 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
8495                 break;
8496             case 1: /* todo: move this to new method fConfirmedEventNotificationRequestTag... */
8497                 tt = proto_tree_add_text(tree, tvb, offset, 1, "notification: ");
8498                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
8499                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8500                 offset  = fConfirmedEventNotificationRequest(tvb, pinfo, subtree, offset);
8501                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8502                 break;
8503             case 2:
8504                 offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
8505                 break;
8506             default:
8507                 return offset;
8508             }
8509             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8510             break;
8511         default:
8512             return offset;
8513         }
8514         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8515     }
8516     return offset;
8517 }
8518
8519 static guint
8520 fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8521 {
8522     guint   lastoffset = 0;
8523     guint8  tag_no, tag_info;
8524     guint32 lvt;
8525
8526     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8527         lastoffset = offset;
8528         switch (fTagNo(tvb, offset)) {
8529         case 0: /* timestamp */
8530             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8531             offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
8532             offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
8533             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8534             break;
8535         case 1: /* logDatum: don't loop, it's a CHOICE */
8536             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8537             switch (fTagNo(tvb, offset)) {
8538             case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
8539                 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
8540                 break;
8541             case 1:
8542                 offset = fBooleanTag(tvb, pinfo, tree, offset, "boolean-value: ");
8543                 break;
8544             case 2:
8545                 offset = fRealTag(tvb, pinfo, tree, offset, "real value: ");
8546                 break;
8547             case 3:
8548                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "enum value: ");
8549                 break;
8550             case 4:
8551                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "unsigned value: ");
8552                 break;
8553             case 5:
8554                 offset = fSignedTag(tvb, pinfo, tree, offset, "signed value: ");
8555                 break;
8556             case 6:
8557                 offset = fBitStringTag(tvb, pinfo, tree, offset, "bitstring value: ");
8558                 break;
8559             case 7:
8560                 offset = fNullTag(tvb, pinfo, tree, offset, "null value: ");
8561                 break;
8562             case 8:
8563                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8564                 offset  = fError(tvb, pinfo, tree, offset);
8565                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8566                 break;
8567             case 9:
8568                 offset = fRealTag(tvb, pinfo, tree, offset, "time change: ");
8569                 break;
8570             case 10:    /* any Value */
8571                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8572                 offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
8573                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8574                 break;
8575             default:
8576                 return offset;
8577             }
8578             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8579             break;
8580         case 2:
8581             /* Changed this to BitString per BACnet Spec. */
8582             offset = fBitStringTagVS(tvb, pinfo, tree, offset, "Status Flags:", BACnetStatusFlags);
8583             break;
8584         default:
8585             return offset;
8586         }
8587         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8588     }
8589     return offset;
8590 }
8591
8592 static guint
8593 fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8594 {
8595     guint   lastoffset = 0;
8596     guint8  tag_no, tag_info;
8597     guint32 lvt;
8598
8599     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8600         lastoffset = offset;
8601         switch (fTagNo(tvb, offset)) {
8602         case 0: /* timestamp */
8603             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8604             offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
8605             offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
8606             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8607             break;
8608         case 1: /* logData: don't loop, it's a CHOICE */
8609             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8610             switch (fTagNo(tvb, offset)) {
8611             case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
8612                 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
8613                 break;
8614             case 1: /* log-data: SEQUENCE OF CHOICE */
8615                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8616                 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset != lastoffset)) {  /* exit loop if nothing happens inside */
8617                     lastoffset = offset;
8618                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8619                     if (tag_is_closing(tag_info)) {
8620                         lastoffset = offset;
8621                         break;
8622                     }
8623                     switch (tag_no) {
8624                     case 0:
8625                         offset = fBooleanTag(tvb, pinfo, tree, offset, "boolean-value: ");
8626                         break;
8627                     case 1:
8628                         offset = fRealTag(tvb, pinfo, tree, offset, "real value: ");
8629                         break;
8630                     case 2:
8631                         offset = fUnsignedTag(tvb, pinfo, tree, offset, "enum value: ");
8632                         break;
8633                     case 3:
8634                         offset = fUnsignedTag(tvb, pinfo, tree, offset, "unsigned value: ");
8635                         break;
8636                     case 4:
8637                         offset = fSignedTag(tvb, pinfo, tree, offset, "signed value: ");
8638                         break;
8639                     case 5:
8640                         offset = fBitStringTag(tvb, pinfo, tree, offset, "bitstring value: ");
8641                         break;
8642                     case 6:
8643                         offset = fNullTag(tvb, pinfo, tree, offset, "null value: ");
8644                         break;
8645                     case 7:
8646                         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8647                         offset  = fError(tvb, pinfo, tree, offset);
8648                         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8649                         break;
8650                     case 8: /* any Value */
8651                         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8652                         offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
8653                         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8654                         break;
8655                     default:
8656                         return offset;
8657                     }
8658                 }
8659                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8660                 break;
8661             case 2:
8662                 offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
8663                 break;
8664             default:
8665                 return offset;
8666             }
8667             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8668             break;
8669         default:
8670             return offset;
8671         }
8672         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8673     }
8674     return offset;
8675 }
8676
8677
8678 static guint
8679 fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8680 {
8681     guint   lastoffset = 0;
8682     guint8  tag_no, tag_info;
8683     guint32 lvt;
8684
8685     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8686         lastoffset = offset;
8687         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8688         if (tag_is_closing(tag_info)) {
8689             break;
8690         }
8691
8692         switch (tag_no) {
8693         case 0: /* ProcessId */
8694             offset  = fProcessId(tvb, pinfo, tree, offset);
8695             break;
8696         case 1: /* initiating ObjectId */
8697             offset  = fObjectIdentifier(tvb, pinfo, tree, offset);
8698             break;
8699         case 2: /* event ObjectId */
8700             offset  = fObjectIdentifier(tvb, pinfo, tree, offset);
8701             break;
8702         case 3: /* time stamp */
8703             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8704             offset  = fTimeStamp(tvb, pinfo, tree, offset, NULL);
8705             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8706             break;
8707         case 4: /* notificationClass */
8708             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
8709             break;
8710         case 5: /* Priority */
8711             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
8712             break;
8713         case 6: /* EventType */
8714             offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8715                 "Event Type: ", BACnetEventType, 64);
8716             break;
8717         case 7: /* messageText */
8718             offset  = fCharacterString(tvb, pinfo, tree, offset, "message Text: ");
8719             break;
8720         case 8: /* NotifyType */
8721             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
8722                 "Notify Type: ", BACnetNotifyType);
8723             break;
8724         case 9: /* ackRequired */
8725             offset  = fBooleanTag(tvb, pinfo, tree, offset, "ack Required: ");
8726             break;
8727         case 10: /* fromState */
8728             offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8729                 "from State: ", BACnetEventState, 64);
8730             break;
8731         case 11: /* toState */
8732             offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8733                 "to State: ", BACnetEventState, 64);
8734             break;
8735         case 12: /* NotificationParameters */
8736             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8737             offset  = fNotificationParameters(tvb, pinfo, tree, offset);
8738             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8739             break;
8740         default:
8741             break;
8742         }
8743         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8744     }
8745     return offset;
8746 }
8747
8748 static guint
8749 fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8750 {
8751     return fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
8752 }
8753
8754 static guint
8755 fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8756 {
8757     guint       lastoffset = 0, len;
8758     guint8      tag_no, tag_info;
8759     guint32     lvt;
8760     proto_tree *subtree    = tree;
8761     proto_item *tt;
8762
8763     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8764         lastoffset = offset;
8765         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8766         if (tag_is_closing(tag_info)) {
8767             offset += len;
8768             subtree = tree;
8769             continue;
8770         }
8771
8772         switch (tag_no) {
8773         case 0: /* ProcessId */
8774             offset = fProcessId(tvb, pinfo, tree, offset);
8775             break;
8776         case 1: /* initiating DeviceId */
8777             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
8778             break;
8779         case 2: /* monitored ObjectId */
8780             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
8781             break;
8782         case 3: /* time remaining */
8783             offset = fTimeSpan(tvb, pinfo, tree, offset, "Time remaining");
8784             break;
8785         case 4: /* List of Values */
8786             if (tag_is_opening(tag_info)) {
8787                 tt = proto_tree_add_text(subtree, tvb, offset, 1, "list of Values");
8788                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
8789                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8790                 offset  = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
8791                 break;
8792             }
8793             FAULT;
8794             break;
8795         default:
8796             return offset;
8797         }
8798         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8799     }
8800     return offset;
8801 }
8802
8803 static guint
8804 fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8805 {
8806     return fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
8807 }
8808
8809 static guint
8810 fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8811 {
8812     guint   lastoffset = 0;
8813     guint8  tag_no = 0, tag_info = 0;
8814     guint32 lvt = 0;
8815
8816     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8817         lastoffset = offset;
8818         switch (fTagNo(tvb, offset)) {
8819         case 0: /* acknowledgingProcessId */
8820             offset = fUnsignedTag(tvb, pinfo, tree, offset, "acknowledging Process Id: ");
8821             break;
8822         case 1: /* eventObjectId */
8823             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
8824             break;
8825         case 2: /* eventStateAcknowledged */
8826             offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8827                 "event State Acknowledged: ", BACnetEventState, 64);
8828             break;
8829         case 3: /* timeStamp */
8830             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8831             offset  = fTimeStamp(tvb, pinfo, tree, offset, NULL);
8832             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8833             break;
8834         case 4: /* acknowledgementSource */
8835             offset  = fCharacterString(tvb, pinfo, tree, offset, "acknowledgement Source: ");
8836             break;
8837         case 5: /* timeOfAcknowledgement */
8838             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8839             offset  = fTimeStamp(tvb, pinfo, tree, offset, "acknowledgement timestamp: ");
8840             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8841             break;
8842         default:
8843             return offset;
8844         }
8845         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8846     }
8847     return offset;
8848 }
8849
8850 static guint
8851 fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8852 {
8853     guint lastoffset = 0;
8854
8855     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8856         lastoffset = offset;
8857         offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
8858         offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
8859             "alarm State: ", BACnetEventState, 64);
8860         offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
8861             "acknowledged Transitions: ", BACnetEventTransitionBits);
8862         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8863     }
8864     return  offset;
8865 }
8866
8867 static guint
8868 fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8869 {
8870     guint   lastoffset = 0;
8871     guint8  tag_no, tag_info;
8872     guint32 lvt;
8873
8874     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8875         lastoffset = offset;
8876         switch (fTagNo(tvb, offset)) {
8877         case 0: /* acknowledgmentFilter */
8878             offset = fEnumeratedTag(tvb, pinfo, tree, offset,
8879                 "acknowledgment Filter: ", BACnetAcknowledgementFilter);
8880             break;
8881         case 1: /* eventObjectId - OPTIONAL */
8882             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8883             offset  = fRecipientProcess(tvb, pinfo, tree, offset);
8884             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8885             break;
8886         case 2: /* eventStateFilter */
8887             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
8888                 "event State Filter: ", BACnetEventStateFilter);
8889             break;
8890         case 3: /* eventTypeFilter - OPTIONAL */
8891             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
8892                 "event Type Filter: ", BACnetEventType);
8893             break;
8894         case 4: /* priorityFilter */
8895             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8896             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "min Priority: ");
8897             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "max Priority: ");
8898             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8899             break;
8900         case 5: /* notificationClassFilter - OPTIONAL */
8901             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "notification Class Filter: ");
8902             break;
8903         default:
8904             return offset;
8905         }
8906         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8907     }
8908     return offset;
8909 }
8910
8911 static guint
8912 fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8913 {
8914     guint lastoffset = 0;
8915
8916     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8917         lastoffset = offset;
8918         offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
8919         offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
8920             "event Type: ", BACnetEventType, 64);
8921         offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
8922             "event State: ", BACnetEventState);
8923         offset = fApplicationTypes(tvb, pinfo, tree, offset, "Priority: ");
8924         if (tvb_reported_length_remaining(tvb, offset) > 0 && fTagNo(tvb, offset) == 2)  /* Notification Class - OPTIONAL */
8925             offset = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
8926         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8927     }
8928
8929     return  offset;
8930 }
8931
8932 static guint
8933 fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8934 {
8935     if (tvb_reported_length_remaining(tvb, offset) > 0) {
8936         if (fTagNo(tvb, offset) == 0) {
8937             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
8938         }
8939     }
8940     return offset;
8941 }
8942
8943 static guint
8944 flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8945 {
8946     guint       lastoffset = 0;
8947     guint8      tag_no, tag_info;
8948     guint32     lvt;
8949     proto_tree* subtree = tree;
8950     proto_item* ti = 0;
8951
8952     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8953         lastoffset = offset;
8954         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8955         /* we are finished here if we spot a closing tag */
8956         if (tag_is_closing(tag_info)) {
8957             break;
8958         }
8959         switch (tag_no) {
8960         case 0: /* ObjectId */
8961             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
8962             break;
8963         case 1: /* eventState */
8964             offset = fEnumeratedTag(tvb, pinfo, tree, offset,
8965                 "event State: ", BACnetEventState);
8966             break;
8967         case 2: /* acknowledgedTransitions */
8968             offset = fBitStringTagVS(tvb, pinfo, tree, offset,
8969                 "acknowledged Transitions: ", BACnetEventTransitionBits);
8970             break;
8971         case 3: /* eventTimeStamps */
8972             ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventTimeStamps");
8973             if (ti) {
8974                 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
8975             }
8976             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8977             offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
8978             offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
8979             offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
8980             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8981             break;
8982         case 4: /* notifyType */
8983             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
8984                 "Notify Type: ", BACnetNotifyType);
8985             break;
8986         case 5: /* eventEnable */
8987             offset  = fBitStringTagVS(tvb, pinfo, tree, offset,
8988                 "event Enable: ", BACnetEventTransitionBits);
8989             break;
8990         case 6: /* eventPriorities */
8991             ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventPriorities");
8992             if (ti) {
8993                 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
8994             }
8995             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8996             offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-OFFNORMAL Priority: ");
8997             offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-FAULT Priority: ");
8998             offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-NORMAL Priority: ");
8999             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9000             break;
9001         default:
9002             return offset;
9003         }
9004         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9005     }
9006     return offset;
9007 }
9008
9009 static guint
9010 fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9011 {
9012     guint   lastoffset = 0;
9013     guint8  tag_no, tag_info;
9014     guint32 lvt;
9015
9016     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9017     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9018         lastoffset = offset;
9019         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9020         /* we are finished here if we spot a closing tag */
9021         if (tag_is_closing(tag_info)) {
9022             break;
9023         }
9024         offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
9025         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9026     }
9027     return offset;
9028 }
9029
9030 static guint
9031 fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9032 {
9033     guint   lastoffset = 0;
9034     guint8  tag_no, tag_info;
9035     guint32 lvt;
9036
9037     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9038         lastoffset = offset;
9039         switch (fTagNo(tvb, offset)) {
9040         case 0: /* listOfEventSummaries */
9041             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9042             offset  = flistOfEventSummaries(tvb, pinfo, tree, offset);
9043             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9044             break;
9045         case 1: /* moreEvents */
9046             offset  = fBooleanTag(tvb, pinfo, tree, offset, "more Events: ");
9047             break;
9048         default:
9049             return offset;
9050         }
9051         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9052     }
9053     return offset;
9054 }
9055
9056 static guint
9057 fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9058 {
9059     guint       lastoffset = 0, len;
9060     guint8      tag_no, tag_info;
9061     guint32     lvt;
9062     proto_tree *subtree    = tree;
9063     proto_item *tt;
9064
9065     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9066
9067     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9068         lastoffset = offset;
9069         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9070         if (tag_is_closing(tag_info)) {
9071             offset += len;
9072             subtree = tree;
9073             continue;
9074         }
9075
9076         switch (tag_no) {
9077         case 0: /* ObjectId */
9078             offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
9079             break;
9080         case 3: /* listOfElements */
9081             if (tag_is_opening(tag_info)) {
9082                 tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfElements");
9083                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9084                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9085                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
9086                 break;
9087             }
9088             FAULT;
9089             break;
9090         default:
9091             return offset;
9092         }
9093         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9094     }
9095     return offset;
9096 }
9097
9098 static guint
9099 fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9100 {
9101     return fObjectIdentifier(tvb, pinfo, tree, offset);
9102 }
9103
9104 static guint
9105 fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9106 {
9107     guint lastoffset = 0;
9108
9109     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9110         lastoffset = offset;
9111
9112         switch (fTagNo(tvb, offset)) {
9113         case 0: /* timeDuration */
9114             offset = fUnsignedTag(tvb, pinfo, tree, offset, "time Duration: ");
9115             break;
9116         case 1: /* enable-disable */
9117             offset = fEnumeratedTag(tvb, pinfo, tree, offset, "enable-disable: ",
9118                 BACnetEnableDisable);
9119             break;
9120         case 2: /* password - OPTIONAL */
9121             offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
9122             break;
9123         default:
9124             return offset;
9125         }
9126         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9127     }
9128     return offset;
9129 }
9130
9131 static guint
9132 fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9133 {
9134     guint lastoffset = 0;
9135
9136     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9137         lastoffset = offset;
9138
9139         switch (fTagNo(tvb, offset)) {
9140         case 0: /* reinitializedStateOfDevice */
9141             offset = fEnumeratedTag(tvb, pinfo, tree, offset,
9142                 "reinitialized State Of Device: ",
9143                 BACnetReinitializedStateOfDevice);
9144             break;
9145         case 1: /* password - OPTIONAL */
9146             offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
9147             break;
9148         default:
9149             return offset;
9150         }
9151         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9152     }
9153     return offset;
9154 }
9155
9156 static guint
9157 fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9158 {
9159     offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
9160                                           "vtClass: ", BACnetVTClass);
9161     return fApplicationTypes(tvb, pinfo, tree, offset, "local VT Session ID: ");
9162 }
9163
9164 static guint
9165 fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9166 {
9167     return fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
9168 }
9169
9170 static guint
9171 fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9172 {
9173     guint lastoffset = 0;
9174
9175     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9176         lastoffset = offset;
9177         offset= fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
9178         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9179     }
9180     return offset;
9181 }
9182
9183 static guint
9184 fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9185 {
9186     offset= fApplicationTypes(tvb, pinfo, tree, offset, "VT Session ID: ");
9187     offset = fApplicationTypes(tvb, pinfo, tree, offset, "VT New Data: ");
9188     return fApplicationTypes(tvb, pinfo, tree, offset, "VT Data Flag: ");
9189 }
9190
9191 static guint
9192 fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9193 {
9194     guint lastoffset = 0;
9195
9196     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9197         lastoffset = offset;
9198
9199         switch (fTagNo(tvb, offset)) {
9200         case 0: /* BOOLEAN */
9201             offset = fBooleanTag(tvb, pinfo, tree, offset, "all New Data Accepted: ");
9202             break;
9203         case 1: /* Unsigned OPTIONAL */
9204             offset = fUnsignedTag(tvb, pinfo, tree, offset, "accepted Octet Count: ");
9205             break;
9206         default:
9207             return offset;
9208         }
9209         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9210     }
9211     return offset;
9212 }
9213
9214 static guint
9215 fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9216 {
9217     guint lastoffset = 0;
9218
9219     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9220         lastoffset = offset;
9221
9222         switch (fTagNo(tvb, offset)) {
9223         case 0: /* Unsigned32 */
9224             offset = fUnsignedTag(tvb, pinfo, tree, offset, "pseudo Random Number: ");
9225             break;
9226         case 1: /* expected Invoke ID Unsigned8 OPTIONAL */
9227             proto_tree_add_item(tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
9228             break;
9229         case 2: /* Chararacter String OPTIONAL */
9230             offset = fCharacterString(tvb, pinfo, tree, offset, "operator Name: ");
9231             break;
9232         case 3: /* Chararacter String OPTIONAL */
9233             offset = fCharacterString(tvb, pinfo, tree, offset, "operator Password: ");
9234             break;
9235         case 4: /* Boolean OPTIONAL */
9236             offset = fBooleanTag(tvb, pinfo, tree, offset, "start Encyphered Session: ");
9237             break;
9238         default:
9239             return offset;
9240         }
9241         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9242     }
9243     return offset;
9244 }
9245
9246 static guint
9247 fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9248 {
9249     return fApplicationTypes(tvb, pinfo, tree, offset, "modified Random Number: ");
9250 }
9251
9252 static guint
9253 fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9254 {
9255     offset = fObjectIdentifier(tvb, pinfo, tree, offset); /* Requesting Device Identifier */
9256     offset = fAddress(tvb, pinfo, tree, offset);
9257     offset = fObjectIdentifier(tvb, pinfo, tree, offset); /* Remote Device Identifier */
9258     return fAddress(tvb, pinfo, tree, offset);
9259 }
9260
9261 static guint
9262 fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9263 {
9264     /* Same as AddListElement request after service choice */
9265     return fAddListElementRequest(tvb, pinfo, tree, offset);
9266 }
9267
9268 static guint
9269 fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9270 {
9271     return fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
9272 }
9273
9274 static guint
9275 fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9276 {
9277     guint       lastoffset = 0, len;
9278     guint8      tag_no, tag_info;
9279     guint32     lvt;
9280     proto_tree *subtree = tree;
9281
9282     /* set the optional global properties to indicate not-used */
9283     propertyArrayIndex = -1;
9284     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9285         lastoffset = offset;
9286         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9287         if (tag_is_closing(tag_info)) {
9288             offset += len;
9289             subtree = tree;
9290             continue;
9291         }
9292         switch (tag_no) {
9293         case 0: /* objectIdentifier */
9294             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9295             break;
9296         case 1: /* propertyIdentifier */
9297             offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
9298             break;
9299         case 2: /* propertyArrayIndex */
9300             offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
9301             break;
9302         case 3: /* propertyValue */
9303             offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
9304             break;
9305         default:
9306             break;
9307         }
9308         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9309     }
9310     return offset;
9311 }
9312
9313 static guint
9314 fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9315 {
9316     guint       lastoffset = 0;
9317     guint8      tag_no, tag_info;
9318     guint32     lvt;
9319     proto_tree *subtree = tree;
9320
9321     /* set the optional global properties to indicate not-used */
9322     propertyArrayIndex = -1;
9323     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9324         lastoffset = offset;
9325         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9326         /* quit loop if we spot a closing tag */
9327         if (tag_is_closing(tag_info)) {
9328             break;
9329         }
9330
9331         switch (tag_no) {
9332         case 0: /* objectIdentifier */
9333             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9334             break;
9335         case 1: /* propertyIdentifier */
9336             offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
9337             break;
9338         case 2: /* propertyArrayIndex */
9339             offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
9340             break;
9341         case 3: /* propertyValue */
9342             offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
9343             break;
9344         case 4: /* Priority (only used for write) */
9345             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
9346             break;
9347         default:
9348             return offset;
9349         }
9350         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9351     }
9352     return offset;
9353 }
9354
9355 static guint
9356 fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9357 {
9358     guint   lastoffset = 0, len;
9359     guint8  tag_no, tag_info;
9360     guint32 lvt;
9361
9362     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9363         lastoffset = offset;
9364         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9365         /* maybe a listOfwriteAccessSpecifications if we spot a closing tag */
9366         if (tag_is_closing(tag_info)) {
9367             offset += len;
9368             continue;
9369         }
9370
9371         switch (tag_no) {
9372         case 0: /* objectIdentifier */
9373             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9374             break;
9375         case 1: /* listOfPropertyValues */
9376             if (tag_is_opening(tag_info)) {
9377                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9378                 offset  = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
9379                 break;
9380             }
9381             FAULT;
9382             break;
9383         default:
9384             return offset;
9385         }
9386         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9387     }
9388     return offset;
9389 }
9390
9391 static guint
9392 fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9393 {
9394     if (offset >= tvb_reported_length(tvb))
9395         return offset;
9396
9397     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9398     return fWriteAccessSpecification(tvb, pinfo, tree, offset);
9399 }
9400
9401 static guint
9402 fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list)
9403 {
9404     guint   lastoffset = 0;
9405     guint8  tag_no, tag_info;
9406     guint32 lvt;
9407
9408     /* set the optional global properties to indicate not-used */
9409     propertyArrayIndex = -1;
9410     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9411         lastoffset = offset;
9412         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9413         if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
9414             return offset;
9415         } else if (tag_is_opening(tag_info)) { /* opening Tag, but not for me */
9416             return offset;
9417         }
9418         switch (tag_no-tagoffset) {
9419         case 0: /* PropertyIdentifier */
9420             offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
9421             break;
9422         case 1: /* propertyArrayIndex */
9423             offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
9424             if (list != 0) break; /* Continue decoding if this may be a list */
9425         default:
9426             lastoffset = offset; /* Set loop end condition */
9427             break;
9428         }
9429         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9430     }
9431     return offset;
9432 }
9433
9434 static guint
9435 fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list)
9436 {
9437     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9438     return fPropertyReference(tvb, pinfo, tree, offset, 0, list);
9439 }
9440
9441 static guint
9442 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9443 {
9444     guint lastoffset = 0;
9445
9446     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9447         lastoffset = offset;
9448
9449         switch (fTagNo(tvb, offset)) {
9450         case 0: /* ObjectIdentifier */
9451             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9452             break;
9453         case 1: /* PropertyIdentifier and propertyArrayIndex */
9454             offset = fPropertyReference(tvb, pinfo, tree, offset, 1, 0);
9455             col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9456         default:
9457             lastoffset = offset; /* Set loop end condition */
9458             break;
9459         }
9460         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9461     }
9462     return offset;
9463 }
9464
9465 #if 0
9466 static guint
9467 fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, guint offset)
9468 {
9469     guint       lastoffset = 0;
9470     guint8      tag_no, tag_info;
9471     guint32     lvt;
9472     proto_tree* subtree = tree;
9473     proto_item* tt;
9474
9475     while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
9476         lastoffset = offset;
9477         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9478         if (tag_is_closing(tag_info)) {
9479             offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
9480                 &tag_no, &tag_info, &lvt);
9481             continue;
9482         }
9483         switch (tag_no) {
9484         case 0: /* ObjectIdentifier */
9485             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9486             break;
9487         case 1: /* PropertyIdentifier */
9488             offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
9489             break;
9490         case 2: /* propertyArrayIndex */
9491             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "property Array Index: ");
9492             break;
9493         case 3:  /* Value */
9494             offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
9495             break;
9496         case 4:  /* Priority */
9497             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
9498             break;
9499         default:
9500             break;
9501         }
9502     }
9503     return offset;
9504 }
9505 #endif
9506
9507 static guint
9508 fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9509 {
9510     char  i = 1, ar[256];
9511     guint lastoffset = 0;
9512
9513     if (propertyArrayIndex > 0) {
9514         /* BACnetARRAY index 0 refers to the length
9515         of the array, not the elements of the array.
9516         BACnetARRAY index -1 is our internal flag that
9517         the optional index was not used.
9518         BACnetARRAY refers to this as all elements of the array.
9519         If the optional index is specified for a BACnetARRAY,
9520         then that specific array element is referenced. */
9521         i = propertyArrayIndex;
9522     }
9523     while (tvb_reported_length_remaining(tvb, offset) > 0) {
9524         /* exit loop if nothing happens inside */
9525         lastoffset = offset;
9526         g_snprintf(ar, sizeof(ar), "%s[%d]: ",
9527             val_to_split_str(87 , 512,
9528                 BACnetPropertyIdentifier,
9529                 ASHRAE_Reserved_Fmt,
9530                 Vendor_Proprietary_Fmt),
9531             i++);
9532         /* DMR Should be fAbstractNSyntax, but that's where we came from! */
9533         offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9534         /* there are only 16 priority array elements */
9535         if (i > 16) {
9536             break;
9537         }
9538         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9539     }
9540
9541     return offset;
9542 }
9543
9544 static guint
9545 fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9546 {
9547     guint lastoffset = 0;
9548
9549     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9550         lastoffset = offset;
9551
9552         switch (fTagNo(tvb, offset)) {
9553         case 0: /* deviceIdentifier - OPTIONAL */
9554             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9555             break;
9556         case 1: /* ObjectIdentifier */
9557             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9558             break;
9559         default:
9560             return offset;
9561         }
9562         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9563     }
9564     return offset;
9565 }
9566
9567 static guint
9568 fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9569 {
9570     guint8 tag_no, tag_info;
9571     guint32 lvt;
9572     guint lastoffset = 0, len;
9573     gboolean closing_found = FALSE;  /* tracks when we are done decoding the fSpecialEvent entries */
9574
9575     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9576         lastoffset = offset;
9577         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9578         /* maybe a SEQUENCE of SpecialEvents if we spot a closing tag */
9579         if (tag_is_closing(tag_info)) {
9580             /* if we find 2 closing tags in succession we need to exit without incrementing the offset again */
9581             /* This handles the special case where we have a special event entry in an RPM-ACK msg           */
9582             if ( closing_found == TRUE )
9583                 break;
9584             offset += len;
9585             closing_found = TRUE;
9586             continue;
9587         }
9588
9589         switch (tag_no) {
9590         case 0: /* calendarEntry */
9591             if (tag_is_opening(tag_info)) {
9592                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9593                 offset  = fCalendarEntry(tvb, pinfo, subtree, offset);
9594                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9595             }
9596             break;
9597         case 1: /* calendarReference */
9598             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9599             break;
9600         case 2: /* list of BACnetTimeValue */
9601             if (tag_is_opening(tag_info)) {
9602                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9603                 offset  = fTimeValue(tvb, pinfo, subtree, offset);
9604                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9605                 break;
9606             }
9607             FAULT;
9608             break;
9609         case 3: /* eventPriority */
9610             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "event priority: ");
9611             break;
9612         default:
9613             return offset;
9614         }
9615         closing_found = FALSE; /* reset our closing tag status, we processed another open tag */
9616         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9617     }
9618     return offset;
9619 }
9620
9621 static guint
9622 fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9623 {
9624     guint   lastoffset = 0, len;
9625     guint8  tag_no, tag_info;
9626     guint32 lvt;
9627
9628     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9629         lastoffset = offset;
9630         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9631         /* maybe a listOfSelectionCriteria if we spot a closing tag */
9632         if (tag_is_closing(tag_info)) {
9633             offset += len;
9634             continue;
9635         }
9636
9637         switch (fTagNo(tvb, offset)) {
9638         case 0: /* propertyIdentifier */
9639             offset  = fPropertyIdentifier(tvb, pinfo, tree, offset);
9640             break;
9641         case 1: /* propertyArrayIndex */
9642             offset  = fPropertyArrayIndex(tvb, pinfo, tree, offset);
9643             break;
9644         case 2: /* relationSpecifier */
9645             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
9646                 "relation Specifier: ", BACnetRelationSpecifier);
9647             break;
9648         case 3: /* comparisonValue */
9649             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9650             offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
9651             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9652             break;
9653         default:
9654             return offset;
9655         }
9656         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9657     }
9658     return offset;
9659 }
9660
9661 static guint
9662 fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9663 {
9664     guint   lastoffset = 0;
9665     guint8  tag_no, tag_info;
9666     guint32 lvt;
9667
9668     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9669         lastoffset = offset;
9670         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9671         /* quit loop if we spot a closing tag */
9672         if (tag_is_closing(tag_info)) {
9673             break;
9674         }
9675
9676         switch (tag_no) {
9677         case 0: /* selectionLogic */
9678             offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
9679                 "selection Logic: ", BACnetSelectionLogic);
9680             break;
9681         case 1: /* listOfSelectionCriteria */
9682             if (tag_is_opening(tag_info)) {
9683                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9684                 offset  = fSelectionCriteria(tvb, pinfo, subtree, offset);
9685                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9686                 break;
9687             }
9688             FAULT;
9689             break;
9690         default:
9691             return offset;
9692         }
9693         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9694     }
9695     return offset;
9696 }
9697
9698
9699 static guint
9700 fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *subtree, guint offset)
9701 {
9702     guint   lastoffset = 0;
9703     guint8  tag_no, tag_info;
9704     guint32 lvt;
9705
9706     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9707         lastoffset = offset;
9708         fTagHeader (tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9709
9710         if (tag_is_opening(tag_info) && tag_no < 2) {
9711             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9712             switch (tag_no) {
9713             case 0: /* objectSelectionCriteria */
9714                 offset = fObjectSelectionCriteria(tvb, pinfo, subtree, offset);
9715                 break;
9716             case 1: /* listOfPropertyReferences */
9717                 offset = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
9718                 break;
9719             default:
9720                 return offset;
9721             }
9722             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9723         }
9724         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9725     }
9726     return offset;
9727 }
9728
9729 static guint
9730 fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9731 {
9732     guint       lastoffset = 0;
9733     guint8      tag_no, tag_info;
9734     guint32     lvt;
9735     proto_item *tt;
9736     proto_tree *subtree = tree;
9737
9738     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9739         lastoffset = offset;
9740         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9741         switch (tag_no) {
9742         case 0: /* objectIdentifier */
9743             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9744             break;
9745         case 1: /* listOfPropertyReferences */
9746             if (tag_is_opening(tag_info)) {
9747                 tt      = proto_tree_add_text(subtree, tvb, offset, 1, "listOfPropertyReferences");
9748                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9749                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9750                 offset  = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
9751             } else if (tag_is_closing(tag_info)) {
9752                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
9753                     &tag_no, &tag_info, &lvt);
9754                 subtree = tree;
9755             } else {
9756                 /* error condition: let caller handle */
9757                 return offset;
9758             }
9759             break;
9760         default:
9761             return offset;
9762         }
9763         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9764     }
9765     return offset;
9766 }
9767
9768 static guint
9769 fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9770 {
9771     guint       lastoffset = 0, len;
9772     guint8      tag_no;
9773     guint8      tag_info;
9774     guint32     lvt;
9775     proto_tree *subtree = tree;
9776     proto_item *tt;
9777
9778     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9779         lastoffset = offset;
9780         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9781         /* maybe a listOfReadAccessResults if we spot a closing tag here */
9782         if (tag_is_closing(tag_info)) {
9783             offset += len;
9784             if ((tag_no == 4 || tag_no == 5) && (subtree != tree)) subtree = subtree->parent; /* Value and error have extra subtree */
9785             continue;
9786         }
9787
9788         switch (tag_no) {
9789         case 0: /* objectSpecifier */
9790             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9791             break;
9792         case 1: /* list of Results */
9793             if (tag_is_opening(tag_info)) {
9794                 tt = proto_tree_add_text(tree, tvb, offset, 1, "listOfResults");
9795                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9796                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9797                 break;
9798             }
9799             FAULT;
9800             break;
9801         case 2: /* propertyIdentifier */
9802             offset = fPropertyIdentifierValue(tvb, pinfo, subtree, offset, 2);
9803             break;
9804         case 5: /* propertyAccessError */
9805             if (tag_is_opening(tag_info)) {
9806                 tt      = proto_tree_add_text(subtree, tvb, offset, 1, "propertyAccessError");
9807                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9808                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9809                 /* Error Code follows */
9810                 offset  = fError(tvb, pinfo, subtree, offset);
9811                 break;
9812             }
9813             FAULT;
9814             break;
9815         default:
9816             return offset;
9817         }
9818         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9819     }
9820     return offset;
9821 }
9822
9823
9824 static guint
9825 fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9826 {
9827     /* listOfReadAccessResults */
9828     return fReadAccessResult(tvb, pinfo, tree, offset);
9829 }
9830
9831
9832 static guint
9833 fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9834 {
9835     guint   lastoffset = 0;
9836     guint8  tag_no, tag_info;
9837     guint32 lvt;
9838
9839     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9840         lastoffset = offset;
9841         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9842
9843         if (tag_no < 2) {
9844             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9845             switch (tag_no) {
9846             case 0: /* objectSpecifier */
9847                 switch (fTagNo(tvb, offset)) { /* choice of objectType or objectIdentifier */
9848                 case 0: /* objectType */
9849                     offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset, "Object Type: ", BACnetObjectType, 128);
9850                     break;
9851                 case 1: /* objectIdentifier */
9852                     offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9853                     break;
9854                 default:
9855                     break;
9856                 }
9857                 break;
9858             case 1: /* propertyValue */
9859                 if (tag_is_opening(tag_info)) {
9860                     offset = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
9861                     break;
9862                 }
9863                 FAULT;
9864                 break;
9865             default:
9866                 break;
9867             }
9868             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9869         }
9870         if (offset == lastoffset) break;    /* nothing happened, exit loop */
9871     }
9872     return offset;
9873 }
9874
9875 static guint
9876 fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9877 {
9878     return fObjectIdentifier(tvb, pinfo, tree, offset);
9879 }
9880
9881 static guint
9882 fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9883 {
9884     guint8      tag_no, tag_info;
9885     guint32     lvt;
9886     proto_tree *subtree = tree;
9887     proto_item *tt;
9888
9889     offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
9890
9891     if (tvb_reported_length_remaining(tvb, offset) > 0) {
9892         /* optional range choice */
9893         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9894         if (tag_is_opening(tag_info)) {
9895             tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", val_to_str_const(tag_no, BACnetReadRangeOptions, "unknown range option"));
9896             subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9897             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9898             switch (tag_no) {
9899             case 3: /* range byPosition */
9900             case 6: /* range bySequenceNumber, 2004 spec */
9901                 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Index: ");
9902                 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
9903                 break;
9904             case 4: /* range byTime - deprecated in 2004 */
9905             case 7: /* 2004 spec */
9906                 offset = fDateTime(tvb, pinfo, subtree, offset, "reference Date/Time: ");
9907                 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
9908                 break;
9909             case 5: /* range timeRange - deprecated in 2004 */
9910                 offset = fDateTime(tvb, pinfo, subtree, offset, "beginning Time: ");
9911                 offset = fDateTime(tvb, pinfo, subtree, offset, "ending Time: ");
9912                 break;
9913             default:
9914                 break;
9915             }
9916             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9917         }
9918     }
9919     return offset;
9920 }
9921
9922 static guint
9923 fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9924 {
9925     guint8      tag_no, tag_info;
9926     guint32     lvt;
9927     proto_tree *subtree = tree;
9928     proto_item *tt;
9929
9930     /* set the optional global properties to indicate not-used */
9931     propertyArrayIndex = -1;
9932     /* objectIdentifier, propertyIdentifier, and
9933        OPTIONAL propertyArrayIndex */
9934     offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
9935     /* resultFlags => BACnetResultFlags ::= BIT STRING */
9936     offset = fBitStringTagVS(tvb, pinfo, tree, offset,
9937         "resultFlags: ",
9938         BACnetResultFlags);
9939     /* itemCount */
9940     offset = fUnsignedTag(tvb, pinfo, subtree, offset, "item Count: ");
9941     /* itemData */
9942     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9943     if (tag_is_opening(tag_info)) {
9944         col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9945         tt = proto_tree_add_text(subtree, tvb, offset, 1, "itemData");
9946         subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9947         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9948         offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
9949         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9950     }
9951     /* firstSequenceNumber - OPTIONAL */
9952     if (tvb_reported_length_remaining(tvb, offset) > 0) {
9953         offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "first Sequence Number: ");
9954     }
9955
9956     return offset;
9957 }
9958
9959 static guint
9960 fAccessMethod(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9961 {
9962     guint       lastoffset = 0;
9963     guint32     lvt;
9964     guint8      tag_no, tag_info;
9965     proto_item* tt;
9966     proto_tree* subtree = NULL;
9967
9968     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9969
9970     if (tag_is_opening(tag_info)) {
9971         tt = proto_tree_add_text(tree, tvb, offset, 1, "%s", val_to_str_const(tag_no, BACnetFileAccessOption, "invalid access method"));
9972         subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9973         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9974         offset  = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "invalid option"));
9975         offset  = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileWriteInfo, "unknown option"));
9976
9977         if (tag_no == 1) {
9978             while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
9979                 /* exit loop if nothing happens inside */
9980                 lastoffset = offset;
9981                 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "Record Data: ");
9982             }
9983         }
9984
9985         if ((bacapp_flags & BACAPP_MORE_SEGMENTS) == 0) {
9986             /* More Flag is not set, so we can look for closing tag in this segment */
9987             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9988             if (tag_is_closing(tag_info)) {
9989                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9990             }
9991         }
9992     }
9993     return offset;
9994 }
9995
9996 static guint
9997 fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9998 {
9999     guint8      tag_no, tag_info;
10000     guint32     lvt;
10001     proto_tree *subtree = tree;
10002     proto_item *tt;
10003
10004     offset = fObjectIdentifier(tvb, pinfo, tree, offset);
10005
10006     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10007
10008     if (tag_is_opening(tag_info)) {
10009         tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", val_to_str_const(tag_no, BACnetFileAccessOption, "unknown access method"));
10010         subtree = proto_item_add_subtree(tt, ett_bacapp_value);
10011         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10012         offset  = fSignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
10013         offset  = fUnsignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileRequestCount, "unknown option"));
10014         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10015     }
10016     return offset;
10017 }
10018
10019 static guint
10020 fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10021 {
10022
10023     offset = fObjectIdentifier(tvb, pinfo, tree, offset); /* file Identifier */
10024     offset = fAccessMethod(tvb, pinfo, tree, offset);
10025
10026     return offset;
10027 }
10028
10029 static guint
10030 fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10031 {
10032     guint tag_no = fTagNo(tvb, offset);
10033     return fSignedTag(tvb, pinfo, tree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
10034 }
10035
10036 static guint
10037 fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10038 {
10039     offset = fApplicationTypes(tvb, pinfo, tree, offset, "End Of File: ");
10040     offset = fAccessMethod(tvb, pinfo, tree, offset);
10041
10042     return offset;
10043 }
10044
10045 static guint
10046 fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
10047 {
10048     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10049     return fReadAccessSpecification(tvb, pinfo, subtree, offset);
10050 }
10051
10052 static guint
10053 fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10054 {
10055     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10056     return fReadAccessResult(tvb, pinfo, tree, offset);
10057 }
10058
10059 static guint
10060 fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
10061 {
10062     if (tvb_reported_length_remaining(tvb, offset) <= 0)
10063         return offset;
10064
10065     switch (service_choice) {
10066     case 0: /* acknowledgeAlarm */
10067         offset = fAcknowledgeAlarmRequest(tvb, pinfo, tree, offset);
10068         break;
10069     case 1: /* confirmedCOVNotification */
10070         offset = fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
10071         break;
10072     case 2: /* confirmedEventNotification */
10073         offset = fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
10074         break;
10075     case 3: /* confirmedGetAlarmSummary conveys no parameters */
10076         break;
10077     case 4: /* getEnrollmentSummaryRequest */
10078         offset = fGetEnrollmentSummaryRequest(tvb, pinfo, tree, offset);
10079         break;
10080     case 5: /* subscribeCOVRequest */
10081         offset = fSubscribeCOVRequest(tvb, pinfo, tree, offset);
10082         break;
10083     case 6: /* atomicReadFile-Request */
10084         offset = fAtomicReadFileRequest(tvb, pinfo, tree, offset);
10085         break;
10086     case 7: /* atomicWriteFile-Request */
10087         offset = fAtomicWriteFileRequest(tvb, pinfo, tree, offset);
10088         break;
10089     case 8: /* AddListElement-Request */
10090         offset = fAddListElementRequest(tvb, pinfo, tree, offset);
10091         break;
10092     case 9: /* removeListElement-Request */
10093         offset = fRemoveListElementRequest(tvb, pinfo, tree, offset);
10094         break;
10095     case 10: /* createObjectRequest */
10096         offset = fCreateObjectRequest(tvb, pinfo, tree, offset);
10097         break;
10098     case 11: /* deleteObject */
10099         offset = fDeleteObjectRequest(tvb, pinfo, tree, offset);
10100         break;
10101     case 12:
10102         offset = fReadPropertyRequest(tvb, pinfo, tree, offset);
10103         break;
10104     case 13:
10105         offset = fReadPropertyConditionalRequest(tvb, pinfo, tree, offset);
10106         break;
10107     case 14:
10108         offset = fReadPropertyMultipleRequest(tvb, pinfo, tree, offset);
10109         break;
10110     case 15:
10111         offset = fWritePropertyRequest(tvb, pinfo, tree, offset);
10112         break;
10113     case 16:
10114         offset = fWritePropertyMultipleRequest(tvb, pinfo, tree, offset);
10115         break;
10116     case 17:
10117         offset = fDeviceCommunicationControlRequest(tvb, pinfo, tree, offset);
10118         break;
10119     case 18:
10120         offset = fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
10121         break;
10122     case 19:
10123         offset = fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
10124         break;
10125     case 20:
10126         offset = fReinitializeDeviceRequest(tvb, pinfo, tree, offset);
10127         break;
10128     case 21:
10129         offset = fVtOpenRequest(tvb, pinfo, tree, offset);
10130         break;
10131     case 22:
10132         offset = fVtCloseRequest(tvb, pinfo, tree, offset);
10133         break;
10134     case 23:
10135         offset = fVtDataRequest(tvb, pinfo, tree, offset);
10136         break;
10137     case 24:
10138         offset = fAuthenticateRequest(tvb, pinfo, tree, offset);
10139         break;
10140     case 25:
10141         offset = fRequestKeyRequest(tvb, pinfo, tree, offset);
10142         break;
10143     case 26:
10144         offset = fReadRangeRequest(tvb, pinfo, tree, offset);
10145         break;
10146     case 27:
10147         offset = fLifeSafetyOperationRequest(tvb, pinfo, tree, offset, NULL);
10148         break;
10149     case 28:
10150         offset = fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
10151         break;
10152     case 29:
10153         offset = fGetEventInformationRequest(tvb, pinfo, tree, offset);
10154         break;
10155     default:
10156         return offset;
10157     }
10158     return offset;
10159 }
10160
10161 static guint
10162 fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
10163 {
10164     if (tvb_reported_length_remaining(tvb, offset) <= 0)
10165         return offset;
10166
10167     switch (service_choice) {
10168     case 3: /* confirmedEventNotificationAck */
10169         offset = fGetAlarmSummaryAck(tvb, pinfo, tree, offset);
10170         break;
10171     case 4: /* getEnrollmentSummaryAck */
10172         offset = fGetEnrollmentSummaryAck(tvb, pinfo, tree, offset);
10173         break;
10174     case 6: /* atomicReadFile */
10175         offset = fAtomicReadFileAck(tvb, pinfo, tree, offset);
10176         break;
10177     case 7: /* atomicReadFileAck */
10178         offset = fAtomicWriteFileAck(tvb, pinfo, tree, offset);
10179         break;
10180     case 10: /* createObject */
10181         offset = fCreateObjectAck(tvb, pinfo, tree, offset);
10182         break;
10183     case 12:
10184         offset = fReadPropertyAck(tvb, pinfo, tree, offset);
10185         break;
10186     case 13:
10187         offset = fReadPropertyConditionalAck(tvb, pinfo, tree, offset);
10188         break;
10189     case 14:
10190         offset = fReadPropertyMultipleAck(tvb, pinfo, tree, offset);
10191         break;
10192     case 18:
10193         offset = fConfirmedPrivateTransferAck(tvb, pinfo, tree, offset);
10194         break;
10195     case 21:
10196         offset = fVtOpenAck(tvb, pinfo, tree, offset);
10197         break;
10198     case 23:
10199         offset = fVtDataAck(tvb, pinfo, tree, offset);
10200         break;
10201     case 24:
10202         offset = fAuthenticateAck(tvb, pinfo, tree, offset);
10203         break;
10204     case 26:
10205         offset = fReadRangeAck(tvb, pinfo, tree, offset);
10206         break;
10207     case 29:
10208         offset = fGetEventInformationACK(tvb, pinfo, tree, offset);
10209         break;
10210     default:
10211         return offset;
10212     }
10213     return offset;
10214 }
10215
10216 static guint
10217 fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10218 {
10219     /* BACnetObjectIdentifier */
10220     offset = fApplicationTypes(tvb, pinfo, tree, offset, "BACnet Object Identifier: ");
10221
10222     /* MaxAPDULengthAccepted */
10223     offset = fApplicationTypes(tvb, pinfo, tree, offset, "Maximum ADPU Length Accepted: ");
10224
10225     /* segmentationSupported */
10226     offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
10227         "Segmentation Supported: ", BACnetSegmentation);
10228
10229     /* vendor ID */
10230     return fVendorIdentifier(tvb, pinfo, tree, offset);
10231 }
10232
10233 static guint
10234 fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10235 {
10236     /* BACnetDeviceIdentifier */
10237     offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device Identifier: ");
10238
10239     /* BACnetObjectIdentifier */
10240     offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
10241
10242     /* ObjectName */
10243     return fApplicationTypes(tvb, pinfo, tree, offset, "Object Name: ");
10244
10245 }
10246
10247 static guint
10248 fWhoIsRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, guint offset)
10249 {
10250     guint   lastoffset = 0;
10251     guint   val;
10252     guint8  tag_len;
10253
10254     guint8  tag_no, tag_info;
10255     guint32 lvt;
10256
10257     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10258         lastoffset = offset;
10259
10260         tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10261
10262         switch (tag_no) {
10263         case 0:
10264             /* DeviceInstanceRangeLowLimit Optional */
10265             if (col_get_writable(pinfo->cinfo) && fUnsigned32(tvb, offset+tag_len, lvt, &val))
10266                 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
10267             offset = fDevice_Instance(tvb, pinfo, tree, offset,
10268                 hf_Device_Instance_Range_Low_Limit);
10269             break;
10270         case 1:
10271             /* DeviceInstanceRangeHighLimit Optional but
10272                 required if DeviceInstanceRangeLowLimit is there */
10273             if (col_get_writable(pinfo->cinfo) && fUnsigned32(tvb, offset+tag_len, lvt, &val))
10274                 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
10275             offset = fDevice_Instance(tvb, pinfo, tree, offset,
10276                 hf_Device_Instance_Range_High_Limit);
10277             break;
10278         default:
10279             return offset;
10280         }
10281         if (offset == lastoffset) break;     /* nothing happened, exit loop */
10282     }
10283     return offset;
10284 }
10285
10286 static guint
10287 fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
10288 {
10289     if (tvb_reported_length_remaining(tvb, offset) <= 0)
10290         return offset;
10291
10292     switch (service_choice) {
10293     case 0: /* I-Am-Request */
10294         offset = fIAmRequest(tvb, pinfo, tree, offset);
10295         break;
10296     case 1: /* i-Have Request */
10297         offset = fIHaveRequest(tvb, pinfo, tree, offset);
10298     break;
10299     case 2: /* unconfirmedCOVNotification */
10300         offset = fUnconfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
10301         break;
10302     case 3: /* unconfirmedEventNotification */
10303         offset = fUnconfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
10304         break;
10305     case 4: /* unconfirmedPrivateTransfer */
10306         offset = fUnconfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
10307         break;
10308     case 5: /* unconfirmedTextMessage */
10309         offset = fUnconfirmedTextMessageRequest(tvb, pinfo, tree, offset);
10310         break;
10311     case 206: /* utc-time-synchronization-recipients */
10312     case 6: /* timeSynchronization */
10313         offset = fTimeSynchronizationRequest(tvb, pinfo, tree, offset);
10314         break;
10315     case 7: /* who-Has */
10316         offset = fWhoHas(tvb, pinfo, tree, offset);
10317         break;
10318     case 8: /* who-Is */
10319         offset = fWhoIsRequest(tvb, pinfo, tree, offset);
10320         break;
10321     case 9: /* utcTimeSynchronization */
10322         offset = fUTCTimeSynchronizationRequest(tvb, pinfo, tree, offset);
10323         break;
10324     default:
10325         break;
10326     }
10327     return offset;
10328 }
10329
10330 static guint
10331 fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset, guint8 ack,
10332         gint *svc, proto_item **tt)
10333 {
10334     proto_item *tc;
10335     proto_tree *bacapp_tree_control;
10336     gint        tmp;
10337     guint       extra = 2;
10338
10339     bacapp_seq = 0;
10340     tmp = (gint) tvb_get_guint8(tvb, offset);
10341     bacapp_flags = tmp & 0x0f;
10342
10343     if (ack == 0) {
10344         extra = 3;
10345     }
10346     *svc = (gint) tvb_get_guint8(tvb, offset+extra);
10347     if (bacapp_flags & 0x08)
10348         *svc = (gint) tvb_get_guint8(tvb, offset+extra+2);
10349
10350     proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
10351     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_pduflags, tvb, offset, 1, ENC_BIG_ENDIAN);
10352     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp_control);
10353
10354     proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, ENC_BIG_ENDIAN);
10355     proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, ENC_BIG_ENDIAN);
10356     if (ack == 0) { /* The following are for ConfirmedRequest, not Complex ack */
10357         proto_tree_add_item(bacapp_tree_control, hf_bacapp_SA, tvb, offset++, 1, ENC_BIG_ENDIAN);
10358         proto_tree_add_item(bacapp_tree, hf_bacapp_response_segments, tvb,
10359                             offset, 1, ENC_BIG_ENDIAN);
10360         proto_tree_add_item(bacapp_tree, hf_bacapp_max_adpu_size, tvb,
10361                             offset, 1, ENC_BIG_ENDIAN);
10362     }
10363     offset++;
10364     proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
10365     if (bacapp_flags & 0x08) {
10366         bacapp_seq = tvb_get_guint8(tvb, offset);
10367         proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
10368             offset++, 1, ENC_BIG_ENDIAN);
10369         proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
10370             offset++, 1, ENC_BIG_ENDIAN);
10371     }
10372     *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
10373                   offset++, 1, ENC_BIG_ENDIAN);
10374     return offset;
10375 }
10376
10377 static guint
10378 fContinueConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
10379 {   /* BACnet-Confirmed-Request */
10380     /* ASHRAE 135-2001 20.1.2 */
10381
10382     return fConfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, svc);
10383 }
10384
10385 static guint
10386 fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10387 {   /* BACnet-Confirmed-Request */
10388     /* ASHRAE 135-2001 20.1.2 */
10389     gint        svc;
10390     proto_item *tt = 0;
10391
10392     offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 0, &svc, &tt);
10393     return fContinueConfirmedRequestPDU(tvb, pinfo, bacapp_tree, offset, svc);
10394 }
10395
10396 static guint
10397 fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10398 {   /* BACnet-Unconfirmed-Request-PDU */
10399     /* ASHRAE 135-2001 20.1.3 */
10400
10401     gint tmp;
10402
10403     proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10404
10405     tmp = tvb_get_guint8(tvb, offset);
10406     proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
10407         offset++, 1, ENC_BIG_ENDIAN);
10408     /* Service Request follows... Variable Encoding 20.2ff */
10409     return fUnconfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, tmp);
10410 }
10411
10412 static guint
10413 fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10414 {   /* BACnet-Simple-Ack-PDU */
10415     /* ASHRAE 135-2001 20.1.4 */
10416
10417     proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10418
10419     proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
10420                 offset++, 1, ENC_BIG_ENDIAN);
10421     proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
10422                 offset++, 1, ENC_BIG_ENDIAN);
10423
10424     return offset;
10425 }
10426
10427 static guint
10428 fContinueComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
10429 {   /* BACnet-Complex-Ack-PDU */
10430     /* ASHRAE 135-2001 20.1.5 */
10431
10432     /* Service ACK follows... */
10433     return fConfirmedServiceAck(tvb, pinfo, bacapp_tree, offset, svc);
10434 }
10435
10436 static guint
10437 fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10438 {   /* BACnet-Complex-Ack-PDU */
10439     /* ASHRAE 135-2001 20.1.5 */
10440     gint        svc;
10441     proto_item *tt = 0;
10442
10443     offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 1, &svc, &tt);
10444     return fContinueComplexAckPDU(tvb, pinfo, bacapp_tree, offset, svc);
10445 }
10446
10447 static guint
10448 fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10449 {   /* BACnet-SegmentAck-PDU */
10450     /* ASHRAE 135-2001 20.1.6 */
10451
10452     proto_item *tc;
10453     proto_tree *bacapp_tree_control;
10454
10455     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
10456     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10457
10458     proto_tree_add_item(bacapp_tree_control, hf_bacapp_NAK, tvb, offset, 1, ENC_BIG_ENDIAN);
10459     proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
10460     proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10461                 offset++, 1, ENC_BIG_ENDIAN);
10462     proto_tree_add_item(bacapp_tree_control, hf_bacapp_sequence_number, tvb,
10463                 offset++, 1, ENC_BIG_ENDIAN);
10464     proto_tree_add_item(bacapp_tree_control, hf_bacapp_window_size, tvb,
10465                 offset++, 1, ENC_BIG_ENDIAN);
10466     return offset;
10467 }
10468
10469 static guint
10470 fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10471 {
10472     guint8  tag_info   = 0;
10473     guint8  parsed_tag = 0;
10474     guint32 lvt        = 0;
10475
10476     offset += fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
10477     offset  = fError(tvb, pinfo, tree, offset);
10478     return offset + fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
10479 }
10480
10481 static guint
10482 fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10483 {
10484     guint       lastoffset        = 0;
10485     guint8      tag_no            = 0, tag_info = 0;
10486     guint32     lvt               = 0;
10487     proto_tree *subtree           = tree;
10488     proto_item *tt;
10489
10490     guint       vendor_identifier = 0;
10491     guint       service_number    = 0;
10492     guint8      tag_len           = 0;
10493
10494     while (tvb_reported_length_remaining(tvb, offset) > 0) {
10495         /* exit loop if nothing happens inside */
10496         lastoffset = offset;
10497         tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10498         switch (tag_no) {
10499         case 0: /* errorType */
10500             offset = fContextTaggedError(tvb, pinfo, subtree, offset);
10501             break;
10502         case 1: /* vendorID */
10503             fUnsigned32(tvb, offset+tag_len, lvt, &vendor_identifier);
10504             if (col_get_writable(pinfo->cinfo))
10505                 col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ",    vendor_identifier);
10506             offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
10507             break;
10508         case 2: /* serviceNumber */
10509             fUnsigned32(tvb, offset+tag_len, lvt, &service_number);
10510             if (col_get_writable(pinfo->cinfo))
10511                 col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ",   service_number);
10512             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
10513             break;
10514         case 3: /* errorParameters */
10515             if (tag_is_opening(tag_info)) {
10516                 tt = proto_tree_add_text(subtree, tvb, offset, 1,
10517                     "error Parameters");
10518                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
10519                 propertyIdentifier = -1;
10520                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10521                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10522             } else if (tag_is_closing(tag_info)) {
10523                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
10524                     &tag_no, &tag_info, &lvt);
10525                 subtree = tree;
10526             } else {
10527                 /* error condition: let caller handle */
10528                 return offset;
10529             }
10530             break;
10531         default:
10532             return offset;
10533         }
10534         if (offset == lastoffset) break;     /* nothing happened, exit loop */
10535     }
10536     return offset;
10537 }
10538
10539 static guint
10540 fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10541 {
10542     guint lastoffset = 0;
10543
10544     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10545         lastoffset = offset;
10546         switch (fTagNo(tvb, offset)) {
10547         case 0: /* errorType */
10548             offset = fContextTaggedError(tvb, pinfo, tree, offset);
10549             break;
10550         case 1: /* firstFailedElementNumber */
10551             offset = fUnsignedTag(tvb, pinfo, tree, offset, "first failed element number: ");
10552             break;
10553         default:
10554             return offset;
10555         }
10556         if (offset == lastoffset) break;     /* nothing happened, exit loop */
10557     }
10558     return offset;
10559 }
10560
10561 static guint
10562 fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10563 {
10564     /* Identical to CreateObjectError */
10565     return fCreateObjectError(tvb, pinfo, tree, offset);
10566 }
10567
10568 static guint
10569 fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10570 {
10571     guint8  tag_no = 0, tag_info = 0;
10572     guint32 lvt = 0;
10573
10574     if (fTagNo(tvb, offset) == 0) {
10575         /* errorType */
10576         offset = fContextTaggedError(tvb, pinfo, tree, offset);
10577         if (fTagNo(tvb, offset) == 1) {
10578             /* listOfVTSessionIdentifiers [OPTIONAL] */
10579             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10580             offset  = fVtCloseRequest(tvb, pinfo, tree, offset);
10581             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10582         }
10583     }
10584     /* should report bad packet if initial tag wasn't 0 */
10585     return offset;
10586 }
10587
10588 static guint
10589 fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10590 {
10591     guint   lastoffset = 0;
10592     guint8  tag_no     = 0, tag_info = 0;
10593     guint32 lvt        = 0;
10594
10595     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10596     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10597         lastoffset = offset;
10598         switch (fTagNo(tvb, offset)) {
10599         case 0: /* errorType */
10600             offset = fContextTaggedError(tvb, pinfo, tree, offset);
10601             break;
10602         case 1: /* firstFailedWriteAttempt */
10603             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10604             offset  = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
10605             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10606             break;
10607         default:
10608             return offset;
10609         }
10610         if (offset == lastoffset) break;     /* nothing happened, exit loop */
10611     }
10612     return offset;
10613 }
10614
10615 static guint
10616 fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10617 {
10618     offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
10619                            "error Class: ", BACnetErrorClass, 64);
10620     return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
10621                          "error Code: ", BACnetErrorCode, 256);
10622 }
10623
10624 static guint
10625 fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service)
10626 {
10627     switch (service) {
10628     case 8:  /* no break here !!!! */
10629     case 9:
10630         offset = fChangeListError(tvb, pinfo, tree, offset);
10631         break;
10632     case 10:
10633         offset = fCreateObjectError(tvb, pinfo, tree, offset);
10634         break;
10635     case 16:
10636         offset = fWritePropertyMultipleError(tvb, pinfo, tree, offset);
10637         break;
10638     case 18:
10639         offset = fConfirmedPrivateTransferError(tvb, pinfo, tree, offset);
10640         break;
10641     case 22:
10642         offset = fVTCloseError(tvb, pinfo, tree, offset);
10643         break;
10644     default:
10645         return fError(tvb, pinfo, tree, offset);
10646     }
10647     return offset;
10648 }
10649
10650 static guint
10651 fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10652 {   /* BACnet-Error-PDU */
10653     /* ASHRAE 135-2001 20.1.7 */
10654
10655     proto_item *tc;
10656     proto_tree *bacapp_tree_control;
10657     guint8      tmp;
10658
10659     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10660     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10661
10662     proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10663                 offset++, 1, ENC_BIG_ENDIAN);
10664     tmp = tvb_get_guint8(tvb, offset);
10665     proto_tree_add_item(bacapp_tree_control, hf_bacapp_service, tvb,
10666                  offset++, 1, ENC_BIG_ENDIAN);
10667     /* Error Handling follows... */
10668     return fBACnetError(tvb, pinfo, bacapp_tree, offset, tmp);
10669 }
10670
10671 static guint
10672 fRejectPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10673 {   /* BACnet-Reject-PDU */
10674     /* ASHRAE 135-2001 20.1.8 */
10675
10676     proto_item *tc;
10677     proto_tree *bacapp_tree_control;
10678
10679     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10680     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10681
10682     proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10683                 offset++, 1, ENC_BIG_ENDIAN);
10684     proto_tree_add_item(bacapp_tree_control, hf_BACnetRejectReason, tvb,
10685                 offset++, 1, ENC_BIG_ENDIAN);
10686     return offset;
10687 }
10688
10689 static guint
10690 fAbortPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10691 {   /* BACnet-Abort-PDU */
10692     /* ASHRAE 135-2001 20.1.9 */
10693
10694     proto_item *tc;
10695     proto_tree *bacapp_tree_control;
10696
10697     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
10698     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10699
10700     proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
10701     proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10702                 offset++, 1, ENC_BIG_ENDIAN);
10703     proto_tree_add_item(bacapp_tree_control, hf_BACnetAbortReason, tvb,
10704                 offset++, 1, ENC_BIG_ENDIAN);
10705     return offset;
10706 }
10707
10708 static guint
10709 do_the_dissection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
10710 {
10711     guint8 flag, bacapp_type;
10712     guint  offset = 0;
10713
10714     flag = (gint) tvb_get_guint8(tvb, 0);
10715     bacapp_type = (flag >> 4) & 0x0f;
10716
10717     if (tvb == NULL) {
10718         return 0;
10719     }
10720
10721     /* ASHRAE 135-2001 20.1.1 */
10722     switch (bacapp_type) {
10723     case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST: /* BACnet-Confirmed-Service-Request */
10724         offset = fConfirmedRequestPDU(tvb, pinfo, tree, offset);
10725         break;
10726     case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:   /* BACnet-Unconfirmed-Request-PDU */
10727         offset = fUnconfirmedRequestPDU(tvb, pinfo, tree, offset);
10728         break;
10729     case BACAPP_TYPE_SIMPLE_ACK:    /* BACnet-Simple-Ack-PDU */
10730         offset = fSimpleAckPDU(tvb, pinfo, tree, offset);
10731         break;
10732     case BACAPP_TYPE_COMPLEX_ACK:   /* BACnet-Complex-Ack-PDU */
10733         offset = fComplexAckPDU(tvb, pinfo, tree, offset);
10734         break;
10735     case BACAPP_TYPE_SEGMENT_ACK:   /* BACnet-SegmentAck-PDU */
10736         offset = fSegmentAckPDU(tvb, pinfo, tree, offset);
10737         break;
10738     case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
10739         offset = fErrorPDU(tvb, pinfo, tree, offset);
10740         break;
10741     case BACAPP_TYPE_REJECT:    /* BACnet-Reject-PDU */
10742         offset = fRejectPDU(tvb, pinfo, tree, offset);
10743         break;
10744     case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
10745         offset = fAbortPDU(tvb, pinfo, tree, offset);
10746         break;
10747     }
10748     return offset;
10749 }
10750
10751 static void
10752 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
10753 {
10754     guint8      flag, bacapp_type;
10755     guint       save_fragmented  = FALSE, data_offset = 0, /*bacapp_apdu_size,*/ fragment = FALSE;
10756     tvbuff_t   *new_tvb          = NULL;
10757     guint       offset           = 0;
10758     guint8      bacapp_seqno     = 0;
10759     guint8      bacapp_service, bacapp_reason/*, bacapp_prop_win_size*/;
10760     guint8      bacapp_invoke_id = 0;
10761     proto_item *ti;
10762     proto_tree *bacapp_tree      = NULL;
10763
10764     gint        svc = 0;
10765     proto_item *tt  = 0;
10766     gint8       ack = 0;
10767
10768     /* Strings for BACnet Statistics */
10769     const gchar errstr[]       = "ERROR: ";
10770     const gchar rejstr[]       = "REJECTED: ";
10771     const gchar abortstr[]     = "ABORTED: ";
10772     const gchar sackstr[]      = " (SimpleAck)";
10773     const gchar cackstr[]      = " (ComplexAck)";
10774     const gchar uconfsreqstr[] = " (Unconfirmed Service Request)";
10775     const gchar confsreqstr[]  = " (Confirmed Service Request)";
10776
10777     col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
10778     col_clear(pinfo->cinfo, COL_INFO);
10779
10780     flag = tvb_get_guint8(tvb, 0);
10781     bacapp_type = (flag >> 4) & 0x0f;
10782
10783     /* show some descriptive text in the INFO column */
10784     col_add_fstr(pinfo->cinfo, COL_INFO, "%-16s",
10785         val_to_str_const(bacapp_type, BACnetTypeName, "# unknown APDU #"));
10786
10787     bacinfo.service_type = NULL;
10788     bacinfo.invoke_id = NULL;
10789     bacinfo.instance_ident = NULL;
10790     bacinfo.object_ident = NULL;
10791
10792     switch (bacapp_type) {
10793     case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
10794         /* segmented messages have 2 additional bytes */
10795         if (flag & BACAPP_SEGMENTED_REQUEST) {
10796             fragment = TRUE;
10797             ack = 0;
10798             /* bacapp_apdu_size = fGetMaxAPDUSize(tvb_get_guint8(tvb, offset + 1)); */ /* has 16 values, reserved are 50 Bytes */
10799             bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
10800             bacapp_seqno = tvb_get_guint8(tvb, offset + 3);
10801             /* bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 4); */
10802             bacapp_service = tvb_get_guint8(tvb, offset + 5);
10803             data_offset = 6;
10804         } else {
10805             bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
10806             bacapp_service = tvb_get_guint8(tvb, offset + 3);
10807         }
10808         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ",
10809                         val_to_str_const(bacapp_service,
10810                                          BACnetConfirmedServiceChoice,
10811                                          bacapp_unknown_service_str),
10812                         bacapp_invoke_id);
10813
10814         updateBacnetInfoValue(BACINFO_INVOKEID,
10815                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10816
10817         updateBacnetInfoValue(BACINFO_SERVICE,
10818                               wmem_strconcat(wmem_packet_scope(),
10819                                              val_to_str_const(bacapp_service,
10820                                                               BACnetConfirmedServiceChoice,
10821                                                               bacapp_unknown_service_str),
10822                                              confsreqstr, NULL));
10823         break;
10824     case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
10825         bacapp_service = tvb_get_guint8(tvb, offset + 1);
10826         col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
10827                         val_to_str_const(bacapp_service,
10828                                          BACnetUnconfirmedServiceChoice,
10829                                          bacapp_unknown_service_str));
10830
10831         updateBacnetInfoValue(BACINFO_SERVICE,
10832                               wmem_strconcat(wmem_packet_scope(),
10833                                              val_to_str_const(bacapp_service,
10834                                                               BACnetUnconfirmedServiceChoice,
10835                                                               bacapp_unknown_service_str),
10836                                              uconfsreqstr, NULL));
10837         break;
10838     case BACAPP_TYPE_SIMPLE_ACK:
10839         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10840         bacapp_service = tvb_get_guint8(tvb, offset + 2);
10841         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10842                         val_to_str_const(bacapp_service,
10843                                          BACnetConfirmedServiceChoice,
10844                                          bacapp_unknown_service_str),
10845                         bacapp_invoke_id);
10846
10847         updateBacnetInfoValue(BACINFO_INVOKEID,
10848                               wmem_strdup_printf(wmem_packet_scope(),
10849                                                  "Invoke ID: %d", bacapp_invoke_id));
10850
10851         updateBacnetInfoValue(BACINFO_SERVICE,
10852                               wmem_strconcat(wmem_packet_scope(),
10853                                              val_to_str_const(bacapp_service,
10854                                                               BACnetConfirmedServiceChoice,
10855                                                               bacapp_unknown_service_str),
10856                                              sackstr, NULL));
10857         break;
10858     case BACAPP_TYPE_COMPLEX_ACK:
10859         /* segmented messages have 2 additional bytes */
10860         if (flag & BACAPP_SEGMENTED_REQUEST) {
10861             fragment = TRUE;
10862             ack = 1;
10863             /* bacapp_apdu_size = fGetMaxAPDUSize(0); */ /* has minimum of 50 Bytes */
10864             bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10865             bacapp_seqno = tvb_get_guint8(tvb, offset + 2);
10866             /* bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 3); */
10867             bacapp_service = tvb_get_guint8(tvb, offset + 4);
10868             data_offset = 5;
10869         } else {
10870             bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10871             bacapp_service = tvb_get_guint8(tvb, offset + 2);
10872         }
10873         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10874                         val_to_str_const(bacapp_service,
10875                                          BACnetConfirmedServiceChoice,
10876                                          bacapp_unknown_service_str),
10877                         bacapp_invoke_id);
10878
10879         updateBacnetInfoValue(BACINFO_INVOKEID,
10880                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10881
10882         updateBacnetInfoValue(BACINFO_SERVICE,
10883                               wmem_strconcat(wmem_packet_scope(),
10884                                              val_to_str_const(bacapp_service,
10885                                                               BACnetConfirmedServiceChoice,
10886                                                               bacapp_unknown_service_str),
10887                                              cackstr, NULL));
10888         break;
10889     case BACAPP_TYPE_SEGMENT_ACK:
10890         /* nothing more to add */
10891         break;
10892     case BACAPP_TYPE_ERROR:
10893         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10894         bacapp_service = tvb_get_guint8(tvb, offset + 2);
10895         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10896                         val_to_str_const(bacapp_service,
10897                                          BACnetConfirmedServiceChoice,
10898                                          bacapp_unknown_service_str),
10899                         bacapp_invoke_id);
10900
10901         updateBacnetInfoValue(BACINFO_INVOKEID,
10902                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10903
10904         updateBacnetInfoValue(BACINFO_SERVICE,
10905                               wmem_strconcat(wmem_packet_scope(),
10906                                              errstr,
10907                                              val_to_str_const(bacapp_service,
10908                                                               BACnetConfirmedServiceChoice,
10909                                                               bacapp_unknown_service_str),
10910                                              NULL));
10911         break;
10912     case BACAPP_TYPE_REJECT:
10913         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10914         bacapp_reason = tvb_get_guint8(tvb, offset + 2);
10915         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10916                         val_to_split_str(bacapp_reason,
10917                                          64,
10918                                          BACnetRejectReason,
10919                                          ASHRAE_Reserved_Fmt,
10920                                          Vendor_Proprietary_Fmt), bacapp_invoke_id);
10921
10922         updateBacnetInfoValue(BACINFO_INVOKEID,
10923                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10924
10925         updateBacnetInfoValue(BACINFO_SERVICE,
10926                               wmem_strconcat(wmem_packet_scope(), rejstr,
10927                                              val_to_split_str(bacapp_reason, 64,
10928                                                               BACnetRejectReason,
10929                                                               ASHRAE_Reserved_Fmt,
10930                                                               Vendor_Proprietary_Fmt),
10931                                              NULL));
10932         break;
10933     case BACAPP_TYPE_ABORT:
10934         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10935         bacapp_reason = tvb_get_guint8(tvb, offset + 2);
10936         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10937                         val_to_split_str(bacapp_reason,
10938                                          64,
10939                                          BACnetAbortReason,
10940                                          ASHRAE_Reserved_Fmt,
10941                                          Vendor_Proprietary_Fmt), bacapp_invoke_id);
10942
10943         updateBacnetInfoValue(BACINFO_INVOKEID,
10944                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10945
10946         updateBacnetInfoValue(BACINFO_SERVICE,
10947                               wmem_strconcat(wmem_packet_scope(), abortstr,
10948                                              val_to_split_str(bacapp_reason,
10949                                                               64,
10950                                                               BACnetAbortReason,
10951                                                               ASHRAE_Reserved_Fmt,
10952                                                               Vendor_Proprietary_Fmt),
10953                                              NULL));
10954         break;
10955         /* UNKNOWN */
10956     default:
10957         /* nothing more to add */
10958         break;
10959     }
10960
10961     save_fragmented = pinfo->fragmented;
10962
10963     ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, ENC_NA);
10964     bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
10965
10966     if (!fragment)
10967         do_the_dissection(tvb, pinfo, bacapp_tree);
10968     else
10969         fStartConfirmed(tvb, pinfo, bacapp_tree, offset, ack, &svc, &tt);
10970             /* not resetting the offset so the remaining can be done */
10971
10972     if (fragment) { /* fragmented */
10973         fragment_head *frag_msg;
10974
10975         pinfo->fragmented = TRUE;
10976
10977         frag_msg = fragment_add_seq_check(&msg_reassembly_table,
10978             tvb, data_offset,
10979             pinfo,
10980             bacapp_invoke_id,      /* ID for fragments belonging together */
10981             NULL,
10982             bacapp_seqno,          /* fragment sequence number */
10983             tvb_reported_length_remaining(tvb, data_offset), /* fragment length - to the end */
10984             flag & BACAPP_MORE_SEGMENTS); /* Last fragment reached? */
10985         new_tvb = process_reassembled_data(tvb, data_offset, pinfo,
10986                 "Reassembled BACapp", frag_msg, &msg_frag_items,
10987                 NULL, tree);
10988
10989         if (new_tvb) { /* Reassembled */
10990             col_append_str(pinfo->cinfo, COL_INFO,
10991                            " (Message Reassembled)");
10992         } else { /* Not last packet of reassembled Short Message */
10993             col_append_fstr(pinfo->cinfo, COL_INFO,
10994                             " (Message fragment %u)", bacapp_seqno);
10995         }
10996         if (new_tvb) { /* take it all */
10997             switch (bacapp_type) {
10998             case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
10999                 fContinueConfirmedRequestPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
11000                 break;
11001             case BACAPP_TYPE_COMPLEX_ACK:
11002                 fContinueComplexAckPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
11003                 break;
11004             default:
11005                 /* do nothing */
11006                 break;
11007             }
11008         }
11009     }
11010
11011     pinfo->fragmented = save_fragmented;
11012
11013     /* tapping */
11014     tap_queue_packet(bacapp_tap, pinfo, &bacinfo);
11015 }
11016
11017 static void
11018 bacapp_init_routine(void)
11019 {
11020     reassembly_table_init(&msg_reassembly_table,
11021                           &addresses_reassembly_table_functions);
11022 }
11023
11024 static guint32
11025 fConvertXXXtoUTF8(gchar *in, gsize *inbytesleft, gchar *out, gsize *outbytesleft, const gchar *fromcoding)
11026 {
11027     guint32 i;
11028     GIConv  icd;
11029
11030     if ((icd = g_iconv_open("UTF-8", fromcoding)) != (GIConv) -1) {
11031         i = (guint32) g_iconv(icd, &in, inbytesleft, &out, outbytesleft);
11032         /* g_iconv incremented 'out'; now ensure it's NULL terminated */
11033         out[0] = '\0';
11034
11035         g_iconv_close(icd);
11036         return i;
11037     }
11038
11039     uni_to_string(in, *inbytesleft, out);
11040     out[*inbytesleft] = '\0';
11041     *outbytesleft -= *inbytesleft;
11042     *inbytesleft   = 0;
11043
11044     return 0;
11045 }
11046
11047 static void
11048 uni_to_string(char * data, gsize str_length, char *dest_buf)
11049 {
11050     gint    i;
11051     guint16 c_char;
11052     gsize   length_remaining;
11053
11054     length_remaining = str_length;
11055     dest_buf[0] = '\0';
11056     if (str_length == 0) {
11057         return;
11058     }
11059     for ( i = 0; i < (gint) str_length; i++ ) {
11060         c_char = data[i];
11061         if ((c_char < 0x20) || (c_char > 0x7e)) {
11062             if (c_char != 0x00) {
11063                 c_char = '.';
11064                 dest_buf[i] = c_char & 0xff;
11065             } else {
11066                 i--;
11067                 str_length--;
11068             }
11069         } else {
11070             dest_buf[i] = c_char & 0xff;
11071         }
11072         length_remaining--;
11073
11074         if (length_remaining == 0) {
11075             dest_buf[i+1] = '\0';
11076             return;
11077         }
11078     }
11079     if (i < 0) {
11080         i = 0;
11081     }
11082     dest_buf[i] = '\0';
11083     return;
11084 }
11085
11086 void
11087 proto_register_bacapp(void)
11088 {
11089     static hf_register_info hf[] = {
11090         { &hf_bacapp_type,
11091           { "APDU Type",           "bacapp.type",
11092             FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, NULL, HFILL }
11093         },
11094         { &hf_bacapp_pduflags,
11095           { "PDU Flags",          "bacapp.pduflags",
11096             FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }
11097         },
11098         { &hf_bacapp_SEG,
11099           { "Segmented Request",           "bacapp.segmented_request",
11100             FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, NULL, HFILL }
11101         },
11102         { &hf_bacapp_MOR,
11103           { "More Segments",           "bacapp.more_segments",
11104             FT_BOOLEAN, 8, TFS(&more_follow), 0x04, "More Segments Follow", HFILL }
11105         },
11106         { &hf_bacapp_SA,
11107           { "SA",           "bacapp.SA",
11108             FT_BOOLEAN, 8, TFS(&segmented_accept), 0x02, "Segmented Response accepted", HFILL }
11109         },
11110         { &hf_bacapp_max_adpu_size,
11111           { "Size of Maximum ADPU accepted",           "bacapp.max_adpu_size",
11112             FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, NULL, HFILL }
11113         },
11114         { &hf_bacapp_response_segments,
11115           { "Max Response Segments accepted",           "bacapp.response_segments",
11116             FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, NULL, HFILL }
11117         },
11118         { &hf_bacapp_objectType,
11119           { "Object Type",           "bacapp.objectType",
11120             FT_UINT32, BASE_DEC, VALS(BACnetObjectType), 0xffc00000, NULL, HFILL }
11121         },
11122         { &hf_bacapp_instanceNumber,
11123           { "Instance Number",           "bacapp.instance_number",
11124             FT_UINT32, BASE_DEC, NULL, 0x003fffff, NULL, HFILL }
11125         },
11126         { &hf_BACnetPropertyIdentifier,
11127           { "Property Identifier", "bacapp.property_identifier",
11128             FT_UINT32, BASE_DEC, VALS(BACnetPropertyIdentifier), 0, NULL, HFILL }
11129         },
11130         { &hf_BACnetVendorIdentifier,
11131           { "Vendor Identifier", "bacapp.vendor_identifier",
11132             FT_UINT16, BASE_DEC|BASE_EXT_STRING, &BACnetVendorIdentifiers_ext, 0, NULL, HFILL }
11133         },
11134         { &hf_BACnetRestartReason,
11135           { "Restart Reason", "bacapp.restart_reason",
11136             FT_UINT8, BASE_DEC, VALS(BACnetRestartReason), 0, NULL, HFILL }
11137         },
11138         { &hf_bacapp_invoke_id,
11139           { "Invoke ID",           "bacapp.invoke_id",
11140             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11141         },
11142         { &hf_bacapp_sequence_number,
11143           { "Sequence Number",           "bacapp.sequence_number",
11144             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11145         },
11146         { &hf_bacapp_window_size,
11147           { "Proposed Window Size",           "bacapp.window_size",
11148             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11149         },
11150         { &hf_bacapp_service,
11151           { "Service Choice",           "bacapp.confirmed_service",
11152             FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, NULL, HFILL }
11153         },
11154         { &hf_bacapp_uservice,
11155           { "Unconfirmed Service Choice",           "bacapp.unconfirmed_service",
11156             FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, NULL, HFILL }
11157         },
11158         { &hf_bacapp_NAK,
11159           { "NAK",           "bacapp.NAK",
11160             FT_BOOLEAN, 8, NULL, 0x02, "negative ACK", HFILL }
11161         },
11162         { &hf_bacapp_SRV,
11163           { "SRV",           "bacapp.SRV",
11164             FT_BOOLEAN, 8, NULL, 0x01, "Server", HFILL }
11165         },
11166         { &hf_Device_Instance_Range_Low_Limit,
11167           { "Device Instance Range Low Limit", "bacapp.who_is.low_limit",
11168             FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
11169         },
11170         { &hf_Device_Instance_Range_High_Limit,
11171           { "Device Instance Range High Limit", "bacapp.who_is.high_limit",
11172             FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
11173         },
11174         { &hf_BACnetRejectReason,
11175           { "Reject Reason",           "bacapp.reject_reason",
11176             FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, NULL, HFILL }
11177         },
11178         { &hf_BACnetAbortReason,
11179           { "Abort Reason",           "bacapp.abort_reason",
11180             FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, NULL, HFILL }
11181         },
11182         { &hf_BACnetApplicationTagNumber,
11183           { "Application Tag Number",
11184             "bacapp.application_tag_number",
11185             FT_UINT8, BASE_DEC, VALS(BACnetApplicationTagNumber), 0xF0,
11186             NULL, HFILL }
11187         },
11188         { &hf_BACnetContextTagNumber,
11189           { "Context Tag Number",
11190             "bacapp.context_tag_number",
11191             FT_UINT8, BASE_DEC, NULL, 0xF0,
11192             NULL, HFILL }
11193         },
11194         { &hf_BACnetExtendedTagNumber,
11195           { "Extended Tag Number",
11196             "bacapp.extended_tag_number",
11197             FT_UINT8, BASE_DEC, NULL, 0,
11198             NULL, HFILL }
11199         },
11200         { &hf_BACnetNamedTag,
11201           { "Named Tag",
11202             "bacapp.named_tag",
11203             FT_UINT8, BASE_DEC, VALS(BACnetTagNames), 0x07,
11204             NULL, HFILL }
11205         },
11206         { &hf_BACnetCharacterSet,
11207           { "String Character Set",
11208             "bacapp.string_character_set",
11209             FT_UINT8, BASE_DEC, VALS(BACnetCharacterSet), 0,
11210             NULL, HFILL }
11211         },
11212         { &hf_BACnetTagClass,
11213           { "Tag Class",           "bacapp.tag_class",
11214             FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, NULL, HFILL }
11215         },
11216         { &hf_bacapp_tag_lvt,
11217           { "Length Value Type",
11218             "bacapp.LVT",
11219             FT_UINT8, BASE_DEC, NULL, 0,
11220             NULL, HFILL }
11221         },
11222         { &hf_bacapp_tag_ProcessId,
11223           { "ProcessIdentifier",           "bacapp.processId",
11224             FT_UINT32, BASE_DEC, NULL, 0, "Process Identifier", HFILL }
11225         },
11226         { &hf_bacapp_tag_IPV4,
11227           { "IPV4",           "bacapp.IPV4",
11228             FT_IPv4, BASE_NONE, NULL, 0, "IP-Address", HFILL }
11229         },
11230         { &hf_bacapp_tag_IPV6,
11231           { "IPV6",           "bacapp.IPV6",
11232             FT_IPv6, BASE_NONE, NULL, 0, "IP-Address", HFILL }
11233         },
11234         { &hf_bacapp_tag_PORT,
11235           { "Port",           "bacapp.Port",
11236             FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
11237         },
11238         {&hf_msg_fragments,
11239          {"Message fragments", "bacapp.fragments",
11240           FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11241         {&hf_msg_fragment,
11242          {"Message fragment", "bacapp.fragment",
11243           FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11244         {&hf_msg_fragment_overlap,
11245          {"Message fragment overlap", "bacapp.fragment.overlap",
11246           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11247         {&hf_msg_fragment_overlap_conflicts,
11248          {"Message fragment overlapping with conflicting data",
11249           "bacapp.fragment.overlap.conflicts",
11250           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11251         {&hf_msg_fragment_multiple_tails,
11252          {"Message has multiple tail fragments",
11253           "bacapp.fragment.multiple_tails",
11254           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11255         {&hf_msg_fragment_too_long_fragment,
11256          {"Message fragment too long", "bacapp.fragment.too_long_fragment",
11257           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11258         {&hf_msg_fragment_error,
11259          {"Message defragmentation error", "bacapp.fragment.error",
11260           FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11261         {&hf_msg_fragment_count,
11262          {"Message fragment count", "bacapp.fragment.count",
11263           FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
11264         {&hf_msg_reassembled_in,
11265          {"Reassembled in", "bacapp.reassembled.in",
11266           FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11267         {&hf_msg_reassembled_length,
11268          {"Reassembled BACapp length", "bacapp.reassembled.length",
11269           FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }
11270     };
11271     static gint *ett[] = {
11272         &ett_bacapp,
11273         &ett_bacapp_control,
11274         &ett_bacapp_tag,
11275         &ett_bacapp_list,
11276         &ett_bacapp_value,
11277         &ett_msg_fragment,
11278         &ett_msg_fragments
11279
11280     };
11281
11282     static ei_register_info ei[] = {
11283         { &ei_bacapp_bad_length, { "bacapp.bad_length", PI_MALFORMED, PI_ERROR, "Wrong length indicated", EXPFILL }},
11284     };
11285
11286     expert_module_t* expert_bacapp;
11287
11288     proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
11289                                            "BACapp", "bacapp");
11290
11291     proto_register_field_array(proto_bacapp, hf, array_length(hf));
11292     proto_register_subtree_array(ett, array_length(ett));
11293     expert_bacapp = expert_register_protocol(proto_bacapp);
11294     expert_register_field_array(expert_bacapp, ei, array_length(ei));
11295     register_dissector("bacapp", dissect_bacapp, proto_bacapp);
11296     register_init_routine(&bacapp_init_routine);
11297
11298     bacapp_dissector_table = register_dissector_table("bacapp.vendor_identifier",
11299                                                       "BACapp Vendor Identifier",
11300                                                       FT_UINT8, BASE_HEX);
11301
11302     /* Register BACnet Statistic trees */
11303     register_bacapp_stat_trees();
11304     bacapp_tap = register_tap("bacapp"); /* BACnet statistics tap */
11305 }
11306
11307 /*
11308  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
11309  *
11310  * Local variables:
11311  * c-basic-offset: 4
11312  * tab-width: 8
11313  * indent-tabs-mode: nil
11314  * End:
11315  *
11316  * vi: set shiftwidth=4 tabstop=8 expandtab:
11317  * :indentSize=4:tabSize=8:noTabs=true:
11318  */