Get rid of a set-but-unused variable.
[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/to_str.h>
36 #include <epan/wmem/wmem.h>
37 #include <epan/reassemble.h>
38 #include <epan/expert.h>
39 #include <epan/stats_tree.h>
40 #include "packet-bacapp.h"
41
42 static int bacapp_tap = -1;
43
44 /* formerly bacapp.h  contains definitions and forward declarations */
45
46 #ifndef FAULT
47 #define FAULT           proto_tree_add_text(subtree, tvb, offset, tvb_length(tvb) - offset, "something is going wrong here !!"); \
48     offset = tvb_length(tvb);
49 #endif
50
51 /* BACnet PDU Types */
52 #define BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST                   0
53 #define BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST                 1
54 #define BACAPP_TYPE_SIMPLE_ACK                                  2
55 #define BACAPP_TYPE_COMPLEX_ACK                                 3
56 #define BACAPP_TYPE_SEGMENT_ACK                                 4
57 #define BACAPP_TYPE_ERROR                                       5
58 #define BACAPP_TYPE_REJECT                                      6
59 #define BACAPP_TYPE_ABORT                                       7
60 #define MAX_BACAPP_TYPE                                         8
61
62 #define BACAPP_SEGMENTED_REQUEST 0x08
63 #define BACAPP_MORE_SEGMENTS 0x04
64 #define BACAPP_SEGMENTED_RESPONSE 0x02
65 #define BACAPP_SEGMENT_NAK 0x02
66 #define BACAPP_SENT_BY 0x01
67
68
69 /**
70  * dissect_bacapp ::= CHOICE {
71  *  confirmed-request-PDU       [0] BACnet-Confirmed-Request-PDU,
72  *  unconfirmed-request-PDU     [1] BACnet-Unconfirmed-Request-PDU,
73  *  simpleACK-PDU               [2] BACnet-SimpleACK-PDU,
74  *  complexACK-PDU              [3] BACnet-ComplexACK-PDU,
75  *  segmentACK-PDU              [4] BACnet-SegmentACK-PDU,
76  *  error-PDU                   [5] BACnet-Error-PDU,
77  *  reject-PDU                  [6] BACnet-Reject-PDU,
78  *  abort-PDU                   [7] BACnet-Abort-PDU
79  * }
80  * @param tvb the tv buffer of the current data
81  * @param pinfo the packet info of the current data
82  * @param tree the tree to append this item to
83  **/
84 static void
85 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
86
87 /**
88  * ConfirmedRequest-PDU ::= SEQUENCE {
89  *  pdu-type                    [0] Unsigned (0..15), -- 0 for this PDU Type
90  *  segmentedMessage            [1] BOOLEAN,
91  *  moreFollows                 [2] BOOLEAN,
92  *  segmented-response-accepted [3] BOOLEAN,
93  *  reserved                    [4] Unsigned (0..3), -- must be set zero
94  *  max-segments-accepted       [5] Unsigned (0..7), -- as per 20.1.2.4
95  *  max-APDU-length-accepted    [5] Unsigned (0..15), -- as per 20.1.2.5
96  *  invokeID                    [6] Unsigned (0..255),
97  *  sequence-number             [7] Unsigned (0..255) OPTIONAL, -- only if segmented msg
98  *  proposed-window-size        [8] Unsigned (0..127) OPTIONAL, -- only if segmented msg
99  *  service-choice              [9] BACnetConfirmedServiceChoice,
100  *  service-request             [10] BACnet-Confirmed-Service-Request OPTIONAL
101  * }
102  * @param tvb the tv buffer of the current data
103  * @param pinfo the packet info of the current data
104  * @param tree the tree to append this item to
105  * @param offset the offset in the tvb
106  * @return modified offset
107  */
108 static guint
109 fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
110
111 /**
112  * @param tvb the tv buffer of the current data
113  * @param pinfo the packet info of the current data
114  * @param tree the tree to append this item to
115  * @param offset the offset in the tvb
116  * @param ack - indocates whether working on request or ack
117  * @param svc - output variable to return service choice
118  * @param tt  - output varable to return service choice item
119  * @return modified offset
120  */
121 static guint
122 fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 ack,
123                 gint *svc, proto_item **tt);
124
125 /**
126  * Unconfirmed-Request-PDU ::= SEQUENCE {
127  *  pdu-type        [0] Unsigned (0..15), -- 1 for this PDU type
128  *  reserved        [1] Unsigned (0..15), -- must be set zero
129  *  service-choice  [2] BACnetUnconfirmedServiceChoice,
130  *  service-request [3] BACnetUnconfirmedServiceRequest -- Context-specific tags 0..3 are NOT used in header encoding
131  * }
132  * @param tvb the tv buffer of the current data
133  * @param pinfo the packet info of the current data
134  * @param tree the tree to append this item to
135  * @param offset the offset in the tvb
136  * @return modified offset
137  */
138 static guint
139 fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
140
141 /**
142  * SimpleACK-PDU ::= SEQUENCE {
143  *  pdu-type            [0] Unsigned (0..15), -- 2 for this PDU type
144  *  reserved            [1] Unsigned (0..15), -- must be set zero
145  *  invokeID            [2] Unsigned (0..255),
146  *  service-ACK-choice  [3] BACnetUnconfirmedServiceChoice -- Context-specific tags 0..3 are NOT used in header encoding
147  * }
148  * @param tvb the tv buffer of the current data
149  * @param pinfo the packet info of the current data
150  * @param tree the tree to append this item to
151  * @param offset the offset in the tvb
152  * @return modified offset
153  */
154 static guint
155 fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
156
157 /**
158  * ComplexACK-PDU ::= SEQUENCE {
159  *  pdu-type                [0] Unsigned (0..15), -- 3 for this PDU Type
160  *  segmentedMessage        [1] BOOLEAN,
161  *  moreFollows             [2] BOOLEAN,
162  *  reserved                [3] Unsigned (0..3), -- must be set zero
163  *  invokeID                [4] Unsigned (0..255),
164  *  sequence-number         [5] Unsigned (0..255) OPTIONAL, -- only if segmented msg
165  *  proposed-window-size    [6] Unsigned (0..127) OPTIONAL, -- only if segmented msg
166  *  service-ACK-choice      [7] BACnetConfirmedServiceChoice,
167  *  service-ACK             [8] BACnet-Confirmed-Service-Request  -- Context-specific tags 0..8 are NOT used in header encoding
168  * }
169  * @param tvb the tv buffer of the current data
170  * @param pinfo the packet info of the current data
171  * @param tree the tree to append this item to
172  * @param offset the offset in the tvb
173  * @return modified offset
174  */
175 static guint
176 fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
177
178 /**
179  * SegmentACK-PDU ::= SEQUENCE {
180  *  pdu-type                [0] Unsigned (0..15), -- 4 for this PDU Type
181  *  reserved                [1] Unsigned (0..3), -- must be set zero
182  *  negative-ACK            [2] BOOLEAN,
183  *  server                  [3] BOOLEAN,
184  *  original-invokeID       [4] Unsigned (0..255),
185  *  sequence-number         [5] Unsigned (0..255),
186  *  actual-window-size      [6] Unsigned (0..127)
187  * }
188  * @param tvb the tv buffer of the current data
189  * @param pinfo the packet info of the current data
190  * @param tree the tree to append this item to
191  * @param offset the offset in the tvb
192  * @return modified offset
193  */
194 static guint
195 fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
196
197 /**
198  * Error-PDU ::= SEQUENCE {
199  *  pdu-type                [0] Unsigned (0..15), -- 5 for this PDU Type
200  *  reserved                [1] Unsigned (0..3), -- must be set zero
201  *  original-invokeID       [2] Unsigned (0..255),
202  *  error-choice            [3] BACnetConfirmedServiceChoice,
203  *  error                   [4] BACnet-Error
204  * }
205  * @param tvb the tv buffer of the current data
206  * @param pinfo the packet info of the current data
207  * @param tree the tree to append this item to
208  * @param offset the offset in the tvb
209  * @return modified offset
210  */
211 static guint
212 fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
213
214 /**
215  * Reject-PDU ::= SEQUENCE {
216  *  pdu-type                [0] Unsigned (0..15), -- 6 for this PDU Type
217  *  reserved                [1] Unsigned (0..3), -- must be set zero
218  *  original-invokeID       [2] Unsigned (0..255),
219  *  reject-reason           [3] BACnetRejectReason
220  * }
221  * @param tvb the tv buffer of the current data
222  * @param pinfo the packet info of the current data
223  * @param tree the tree to append this item to
224  * @param offset the offset in the tvb
225  * @return modified offset
226  */
227 static guint
228 fRejectPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
229
230 /**
231  * Abort-PDU ::= SEQUENCE {
232  *  pdu-type                [0] Unsigned (0..15), -- 7 for this PDU Type
233  *  reserved                [1] Unsigned (0..3), -- must be set zero
234  *  server                  [2] BOOLEAN,
235  *  original-invokeID       [3] Unsigned (0..255),
236  *  abort-reason            [4] BACnetAbortReason
237  * }
238  * @param tvb the tv buffer of the current data
239  * @param pinfo the packet info of the current data
240  * @param tree the tree to append this item to
241  * @param offset the offset in the tvb
242  * @return modified offset
243  */
244 static guint
245 fAbortPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
246
247 /**
248  * 20.2.4, adds the label with max 64Bit unsigned Integer Value to tree
249  * @param tvb the tv buffer of the current data
250  * @param pinfo the packet info of the current data
251  * @param tree the tree to append this item to
252  * @param offset the offset in the tvb
253  * @param label the label of this item
254  * @return modified offset
255  */
256 static guint
257 fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
258
259 /**
260  * 20.2.5, adds the label with max 64Bit signed Integer Value to tree
261  * @param tvb the tv buffer of the current data
262  * @param pinfo the packet info of the current data
263  * @param tree the tree to append this item to
264  * @param offset the offset in the tvb
265  * @param label the label of this item
266  * @return modified offset
267  */
268 static guint
269 fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
270
271 /**
272  * 20.2.8, adds the label with Octet String to tree; if lvt == 0 then lvt = restOfFrame
273  * @param tvb the tv buffer of the current data
274  * @param pinfo the packet info of the current data
275  * @param tree the tree to append this item to
276  * @param offset the offset in the tvb
277  * @param label the label of this item
278  * @param lvt length of String
279  * @return modified offset
280  */
281 static guint
282 fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt);
283
284 /**
285  * 20.2.12, adds the label with Date Value to tree
286  * @param tvb the tv buffer of the current data
287  * @param pinfo the packet info of the current data
288  * @param tree the tree to append this item to
289  * @param offset the offset in the tvb
290  * @param label the label of this item
291  * @return modified offset
292  */
293 static guint
294 fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
295
296 /**
297  * 20.2.13, adds the label with Time Value to tree
298  * @param tvb the tv buffer of the current data
299  * @param pinfo the packet info of the current data
300  * @param tree the tree to append this item to
301  * @param offset the offset in the tvb
302  * @param label the label of this item
303  * @return modified offset
304  */
305 static guint
306 fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
307
308 /**
309  * 20.2.14, adds Object Identifier to tree
310  * use BIG ENDIAN: Bits 31..22 Object Type, Bits 21..0 Instance Number
311  * @param tvb the tv buffer of the current data
312  * @param pinfo the packet info of the current data
313  * @param tree the tree to append this item to
314  * @param offset the offset in the tvb
315  * @return modified offset
316  */
317 static guint
318 fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
319
320 /**
321  * BACnet-Confirmed-Service-Request ::= CHOICE {
322  * }
323  * @param tvb the tv buffer of the current data
324  * @param pinfo the packet info of the current data
325  * @param tree the tree to append this item to
326  * @param offset the offset in the tvb
327  * @param service_choice the service choice
328  * @return offset
329  */
330 static guint
331 fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
332
333 /**
334  * BACnet-Confirmed-Service-ACK ::= CHOICE {
335  * }
336  * @param tvb the tv buffer of the current data
337  * @param pinfo the packet info of the current data
338  * @param tree the tree to append this item to
339  * @param offset the offset in the tvb
340  * @param service_choice the service choice
341  * @return offset
342  */
343 static guint
344 fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
345
346 /**
347  * AcknowledgeAlarm-Request ::= SEQUENCE {
348  *  acknowledgingProcessIdentifier [0] Unsigned32,
349  *  eventObjectIdentifier          [1] BACnetObjectIdentifer,
350  *  eventStateAcknowledge          [2] BACnetEventState,
351  *  timeStamp                      [3] BACnetTimeStamp,
352  *  acknowledgementSource          [4] Character String,
353  *  timeOfAcknowledgement          [5] BACnetTimeStamp
354  * }
355  * @param tvb the tv buffer of the current data
356  * @param pinfo the packet info of the current data
357  * @param tree the tree to append this item to
358  * @param offset the offset in the tvb
359  * @return modified offset
360  */
361 static guint
362 fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
363
364 /**
365  * ConfirmedCOVNotification-Request ::= SEQUENCE {
366  *  subscriberProcessIdentifier [0] Unsigned32,
367  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
368  *  monitoredObjectIdentifier   [2] BACnetObjectIdentifer,
369  *  timeRemaining               [3] unsigned,
370  *  listOfValues                [4] SEQUENCE OF BACnetPropertyValues
371  * }
372  * @param tvb the tv buffer of the current data
373  * @param pinfo the packet info of the current data
374  * @param tree the tree to append this item to
375  * @param offset the offset in the tvb
376  * @return modified offset
377  */
378 static guint
379 fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
380
381 /**
382  * ConfirmedEventNotification-Request ::= SEQUENCE {
383  *  ProcessIdentifier           [0] Unsigned32,
384  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
385  *  eventObjectIdentifier       [2] BACnetObjectIdentifer,
386  *  timeStamp                   [3] BACnetTimeStamp,
387  *  notificationClass           [4] unsigned,
388  *  priority                    [5] unsigned8,
389  *  eventType                   [6] BACnetEventType,
390  *  messageText                 [7] CharacterString OPTIONAL,
391  *  notifyType                  [8] BACnetNotifyType,
392  *  ackRequired                 [9] BOOLEAN OPTIONAL,
393  *  fromState                  [10] BACnetEventState OPTIONAL,
394  *  toState                    [11] BACnetEventState,
395  *  eventValues                [12] BACnetNotificationParameters OPTIONAL
396  * }
397  * @param tvb the tv buffer of the current data
398  * @param pinfo the packet info of the current data
399  * @param tree the tree to append this item to
400  * @param offset the offset in the tvb
401  * @return modified offset
402  */
403 static guint
404 fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo,  proto_tree *tree, guint offset);
405
406 /**
407  * GetAlarmSummary-ACK ::= SEQUENCE OF SEQUENCE {
408  *  objectIdentifier         BACnetObjectIdentifer,
409  *  alarmState               BACnetEventState,
410  *  acknowledgedTransitions  BACnetEventTransitionBits
411  * }
412  * @param tvb the tv buffer of the current data
413  * @param pinfo the packet info of the current data
414  * @param tree the tree to append this item to
415  * @param offset the offset in the tvb
416  * @return modified offset
417  */
418 static guint
419 fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
420
421 /**
422  * GetEnrollmentSummary-Request ::= SEQUENCE {
423  *  acknowledgmentFilter    [0] ENUMERATED {
424  *      all       (0),
425  *      acked     (1),
426  *      not-acked (2)
427  *      },
428  *  enrollmentFilter        [1] BACnetRecipientProcess OPTIONAL,
429  *  eventStateFilter        [2] ENUMERATED {
430  *      offnormal (0),
431  *      fault     (1),
432  *      normal    (2),
433  *      all       (3),
434  *      active    (4)
435  *      },
436  *  eventTypeFilter         [3] BACnetEventType OPTIONAL,
437  *  priorityFilter          [4] SEQUENCE {
438  *      minPriority [0] Unsigned8,
439  *      maxPriority [1] Unsigned8
440  *      } OPTIONAL,
441  *  notificationClassFilter [5] Unsigned OPTIONAL
442  * }
443  * @param tvb the tv buffer of the current data
444  * @param pinfo the packet info of the current data
445  * @param tree the tree to append this item to
446  * @param offset the offset in the tvb
447  * @return modified offset
448  */
449 static guint
450 fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
451
452 /**
453  * GetEnrollmentSummary-ACK ::= SEQUENCE OF SEQUENCE {
454  *  objectIdentifier    BACnetObjectIdentifer,
455  *  eventType           BACnetEventType,
456  *  eventState          BACnetEventState,
457  *  priority            Unsigned8,
458  *  notificationClass   Unsigned OPTIONAL
459  * }
460  * @param tvb the tv buffer of the current data
461  * @param pinfo the packet info of the current data
462  * @param tree the tree to append this item to
463  * @param offset the offset in the tvb
464  * @return modified offset
465  */
466 static guint
467 fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
468
469 /**
470  * GetEventInformation-Request ::= SEQUENCE {
471  *  lastReceivedObjectIdentifier    [0] BACnetObjectIdentifer
472  * }
473  * @param tvb the tv buffer of the current data
474  * @param pinfo the packet info of the current data
475  * @param tree the tree to append this item to
476  * @param offset the offset in the tvb
477  * @return modified offset
478  */
479 static guint
480 fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
481
482 /**
483  * GetEventInformation-ACK ::= SEQUENCE {
484  *  listOfEventSummaries [0] listOfEventSummaries,
485  *  moreEvents           [1] BOOLEAN
486  * }
487  * @param tvb the tv buffer of the current data
488  * @param pinfo the packet info of the current data
489  * @param tree the tree to append this item to
490  * @param offset the offset in the tvb
491  * @return modified offset
492  */
493 static guint
494 fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
495
496 /**
497  * LifeSafetyOperation-Request ::= SEQUENCE {
498  *  requestingProcessIdentifier [0] Unsigned32
499  *  requestingSource            [1] CharacterString
500  *  request                     [2] BACnetLifeSafetyOperation
501  *  objectIdentifier            [3] BACnetObjectIdentifier OPTIONAL
502  * }
503  * @param tvb the tv buffer of the current data
504  * @param pinfo the packet info of the current data
505  * @param tree the tree to append this item to
506  * @param offset the offset in the tvb
507  * @return modified offset
508  */
509 static guint
510 fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
511
512 /**
513  * SubscribeCOV-Request ::= SEQUENCE {
514  *  subscriberProcessIdentifier [0] Unsigned32
515  *  monitoredObjectIdentifier   [1] BACnetObjectIdentifier
516  *  issueConfirmedNotifications [2] BOOLEAN OPTIONAL
517  *  lifetime                    [3] Unsigned OPTIONAL
518  * }
519  * @param tvb the tv buffer of the current data
520  * @param pinfo the packet info of the current data
521  * @param tree the tree to append this item to
522  * @param offset the offset in the tvb
523  * @return modified offset
524  */
525 static guint
526 fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
527
528 /**
529  * SubscribeCOVProperty-Request ::= SEQUENCE {
530  *  subscriberProcessIdentifier [0] Unsigned32
531  *  monitoredObjectIdentifier   [1] BACnetObjectIdentifier
532  *  issueConfirmedNotifications [2] BOOLEAN OPTIONAL
533  *  lifetime                    [3] Unsigned OPTIONAL
534  *  monitoredPropertyIdentifier [4] BACnetPropertyReference OPTIONAL
535  *  covIncrement                [5] Unsigned OPTIONAL
536  * }
537  * @param tvb the tv buffer of the current data
538  * @param pinfo the packet info of the current data
539  * @param tree the tree to append this item to
540  * @param offset the offset in the tvb
541  * @return modified offset
542  */
543 static guint
544 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
545
546 /**
547  * AtomicReadFile-Request ::= SEQUENCE {
548  *  fileIdentifier  BACnetObjectIdentifier,
549  *  accessMethod    CHOICE {
550  *      streamAccess    [0] SEQUENCE {
551  *          fileStartPosition   INTEGER,
552  *          requestedOctetCount Unsigned
553  *          },
554  *      recordAccess    [1] SEQUENCE {
555  *          fileStartRecord      INTEGER,
556  *          requestedRecordCount Unsigned
557  *          }
558  *      }
559  * }
560  * @param tvb the tv buffer of the current data
561  * @param pinfo the packet info of the current data
562  * @param tree the tree to append this item to
563  * @param offset the offset in the tvb
564  * @return modified offset
565  */
566 static guint
567 fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
568
569 /**
570  * AtomicWriteFile-ACK ::= SEQUENCE {
571  *  endOfFile   BOOLEAN,
572  *  accessMethod    CHOICE {
573  *      streamAccess    [0] SEQUENCE {
574  *          fileStartPosition   INTEGER,
575  *          fileData            OCTET STRING
576  *          },
577  *      recordAccess    [1] SEQUENCE {
578  *          fileStartRecord     INTEGER,
579  *          returnedRecordCount Unsigned,
580  *          fileRecordData      SEQUENCE OF OCTET STRING
581  *          }
582  *      }
583  * }
584  * @param tvb the tv buffer of the current data
585  * @param pinfo the packet info of the current data
586  * @param tree the tree to append this item to
587  * @param offset the offset in the tvb
588  * @return modified offset
589  */
590 static guint
591 fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
592
593 /**
594  * AtomicWriteFile-Request ::= SEQUENCE {
595  *  fileIdentifier  BACnetObjectIdentifier,
596  *  accessMethod    CHOICE {
597  *      streamAccess    [0] SEQUENCE {
598  *          fileStartPosition  INTEGER,
599  *          fileData           OCTET STRING
600  *          },
601  *      recordAccess    [1] SEQUENCE {
602  *          fileStartRecord    INTEGER,
603  *          recordCount        Unsigned,
604  *          fileRecordData     SEQUENCE OF OCTET STRING
605  *          }
606  *      }
607  * }
608  * @param tvb the tv buffer of the current data
609  * @param pinfo the packet info of the current data
610  * @param tree the tree to append this item to
611  * @param offset the offset in the tvb
612  * @return modified offset
613  */
614 static guint
615 fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
616
617 /**
618  * AtomicWriteFile-ACK ::= SEQUENCE {
619  *      fileStartPosition [0] INTEGER,
620  *      fileStartRecord   [1] INTEGER,
621  * }
622  * @param tvb the tv buffer of the current data
623  * @param pinfo the packet info of the current data
624  * @param tree the tree to append this item to
625  * @param offset the offset in the tvb
626  * @return modified offset
627  */
628 static guint
629 fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
630
631 /**
632  * AddListElement-Request ::= SEQUENCE {
633  *  objectIdentifier   [0] BACnetObjectIdentifier,
634  *  propertyIdentifier [1] BACnetPropertyIdentifier,
635  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
636  *  listOfElements     [3] ABSTRACT-SYNTAX.&Type
637  * }
638  * @param tvb the tv buffer of the current data
639  * @param pinfo the packet info of the current data
640  * @param tree the tree to append this item to
641  * @param offset the offset in the tvb
642  * @return modified offset
643  */
644 static guint
645 fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
646
647 /**
648  * CreateObject-Request ::= SEQUENCE {
649  *  objectSpecifier     [0] ObjectSpecifier,
650  *  listOfInitialValues [1] SEQUENCE OF BACnetPropertyValue OPTIONAL
651  * }
652  * @param tvb the tv buffer of the current data
653  * @param pinfo the packet info of the current data
654  * @param subtree the sub tree to append this item to
655  * @param offset the offset in the tvb
656  * @return modified offset
657  */
658 static guint
659 fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
660
661 /**
662  * CreateObject-Request ::= BACnetObjectIdentifier
663  * @param tvb the tv buffer of the current data
664  * @param pinfo the packet info of the current data
665  * @param tree the tree to append this item to
666  * @param offset the offset in the tvb
667  * @return modified offset
668  */
669 static guint
670 fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
671
672 /**
673  * DeleteObject-Request ::= SEQUENCE {
674  *  ObjectIdentifier    BACnetObjectIdentifer
675  * }
676  * @param tvb the tv buffer of the current data
677  * @param pinfo the packet info of the current data
678  * @param tree the tree to append this item to
679  * @param offset the offset in the tvb
680  * @return modified offset
681  */
682 static guint
683 fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
684
685 /**
686  * ReadProperty-Request ::= SEQUENCE {
687  *  objectIdentifier    [0] BACnetObjectIdentifier,
688  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
689  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
690  * }
691  * @param tvb the tv buffer of the current data
692  * @param pinfo the packet info of the current data
693  * @param tree the tree to append this item to
694  * @param offset the offset in the tvb
695  * @return modified offset
696  */
697 static guint
698 fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
699
700 /**
701  * ReadProperty-ACK ::= SEQUENCE {
702  *  objectIdentifier   [0] BACnetObjectIdentifier,
703  *  propertyIdentifier [1] BACnetPropertyIdentifier,
704  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
705  *  propertyValue      [3] ABSTRACT-SYNTAX.&Type
706  * }
707  * @param tvb the tv buffer of the current data
708  * @param pinfo the packet info of the current data
709  * @param tree the tree to append this item to
710  * @param offset the offset in the tvb
711  * @return modified offset
712  */
713 static guint
714 fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
715
716 /**
717  * ReadPropertyConditional-Request ::= SEQUENCE {
718  *  objectSelectionCriteria  [0] objectSelectionCriteria,
719  *  listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference OPTIONAL
720  * }
721  * @param tvb the tv buffer of the current data
722  * @param pinfo the packet info of the current data
723  * @param subtree the  sub tree to append this item to
724  * @param offset the offset in the tvb
725  * @return modified offset
726  */
727 static guint
728 fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
729
730 /**
731  * ReadPropertyConditional-ACK ::= SEQUENCE {
732  *  listOfPReadAccessResults    SEQUENCE OF ReadAccessResult OPTIONAL
733  * }
734  * @param tvb the tv buffer of the current data
735  * @param pinfo the packet info of the current data
736  * @param tree the tree to append this item to
737  * @param offset the offset in the tvb
738  * @return modified offset
739  */
740 static guint
741 fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
742
743 /**
744  * ReadPropertyMultiple-Request ::= SEQUENCE {
745  *  listOfReadAccessSpecs   SEQUENCE OF ReadAccessSpecification
746  * }
747  * @param tvb the tv buffer of the current data
748  * @param pinfo the packet info of the current data
749  * @param subtree the sub tree to append this item to
750  * @param offset the offset in the tvb
751  * @return offset modified
752  */
753 static guint
754 fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
755
756 /**
757  * ReadPropertyMultiple-Ack ::= SEQUENCE {
758  *  listOfReadAccessResults SEQUENCE OF ReadAccessResult
759  * }
760  * @param tvb the tv buffer of the current data
761  * @parma pinfo
762  * @param tree the tree to append this item to
763  * @param offset the offset in the tvb
764  * @return offset modified
765  */
766 static guint
767 fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
768
769 /**
770  * ReadRange-Request ::= SEQUENCE {
771  *  objectIdentifier    [0] BACnetObjectIdentifier,
772  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
773  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
774  *  range   CHOICE {
775  *      byPosition  [3] SEQUENCE {
776  *          referencedIndex Unsigned,
777  *          count INTEGER
778  *          },
779  *      byTime      [4] SEQUENCE {
780  *          referenceTime BACnetDateTime,
781  *          count INTEGER
782  *          },
783  *      timeRange   [5] SEQUENCE {
784  *          beginningTime BACnetDateTime,
785  *          endingTime BACnetDateTime
786  *          },
787  *      } OPTIONAL
788  * }
789  * @param tvb the tv buffer of the current data
790  * @param pinfo the packet info of the current data
791  * @param tree the tree to append this item to
792  * @param offset the offset in the tvb
793  * @return modified offset
794  */
795 static guint
796 fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
797
798 /**
799  * ReadRange-ACK ::= SEQUENCE {
800  *  objectIdentifier   [0] BACnetObjectIdentifier,
801  *  propertyIdentifier [1] BACnetPropertyIdentifier,
802  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
803  *  resultFlags        [3] BACnetResultFlags,
804  *  itemCount          [4] Unsigned,
805  *  itemData           [5] SEQUENCE OF ABSTRACT-SYNTAX.&Type
806  * }
807  * @param tvb the tv buffer of the current data
808  * @param pinfo the packet info of the current data
809  * @param tree the tree to append this item to
810  * @param offset the offset in the tvb
811  * @return modified offset
812  */
813 static guint
814 fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
815
816 /**
817  * RemoveListElement-Request ::= SEQUENCE {
818  *  objectIdentifier    [0] BACnetObjectIdentifier,
819  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
820  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
821  *  listOfElements  [3] ABSTRACT-SYNTAX.&Type
822  * }
823  * @param tvb the tv buffer of the current data
824  * @param pinfo the packet info of the current data
825  * @param tree the tree to append this item to
826  * @param offset the offset in the tvb
827  * @return modified offset
828  */
829 static guint
830 fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
831
832 /**
833  * WriteProperty-Request ::= SEQUENCE {
834  *  objectIdentifier   [0] BACnetObjectIdentifier,
835  *  propertyIdentifier [1] BACnetPropertyIdentifier,
836  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
837  *  propertyValue      [3] ABSTRACT-SYNTAX.&Type
838  *  priority           [4] Unsigned8 (1..16) OPTIONAL --used only when property is commandable
839  * }
840  * @param tvb the tv buffer of the current data
841  * @param pinfo the packet info of the current data
842  * @param tree the tree to append this item to
843  * @param offset the offset in the tvb
844  * @return modified offset
845  */
846 static guint
847 fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
848
849 /**
850  * WritePropertyMultiple-Request ::= SEQUENCE {
851  *  listOfWriteAccessSpecifications SEQUENCE OF WriteAccessSpecification
852  * }
853  * @param tvb the tv buffer of the current data
854  * @param pinfo the packet info of the current data
855  * @param tree the tree to append this item to
856  * @param offset the offset in the tvb
857  * @return modified offset
858  */
859 static guint
860 fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
861
862 /**
863  * DeviceCommunicationControl-Request ::= SEQUENCE {
864  *  timeDuration    [0] Unsigned16 OPTIONAL,
865  *  enable-disable  [1] ENUMERATED {
866  *      enable  (0),
867  *      disable (1)
868  *      },
869  *  password        [2] CharacterString (SIZE(1..20)) OPTIONAL
870  * }
871  * @param tvb the tv buffer of the current data
872  * @param pinfo the packet info of the current data
873  * @param tree the tree to append this item to
874  * @param offset the offset in the tvb
875  * @return modified offset
876  */
877 static guint
878 fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
879
880 /**
881  * ConfirmedPrivateTransfer-Request ::= SEQUENCE {
882  *  vendorID          [0] Unsigned,
883  *  serviceNumber     [1] Unsigned,
884  *  serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
885  * }
886  * @param tvb the tv buffer of the current data
887  * @param pinfo the packet info of the current data
888  * @param tree the tree to append this item to
889  * @param offset the offset in the tvb
890  * @return modified offset
891  */
892 static guint
893 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
894
895 /**
896  * ConfirmedPrivateTransfer-ACK ::= SEQUENCE {
897  *  vendorID      [0] Unsigned,
898  *  serviceNumber [1] Unsigned,
899  *  resultBlock   [2] ABSTRACT-SYNTAX.&Type OPTIONAL
900  * }
901  * @param tvb the tv buffer of the current data
902  * @param pinfo the packet info of the current data
903  * @param tree the tree to append this item to
904  * @param offset the offset in the tvb
905  * @return modified offset
906  */
907 static guint
908 fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
909
910 /**
911  * ConfirmedTextMessage-Request ::=  SEQUENCE {
912  *  textMessageSourceDevice [0] BACnetObjectIdentifier,
913  *  messageClass            [1] CHOICE {
914  *      numeric   [0] Unsigned,
915  *      character [1] CharacterString
916  *      } OPTIONAL,
917  *  messagePriority         [2] ENUMERATED {
918  *      normal (0),
919  *      urgent (1)
920  *      },
921  *  message [3] CharacterString
922  * }
923  * @param tvb the tv buffer of the current data
924  * @param pinfo the packet info of the current data
925  * @param tree the tree to append this item to
926  * @param offset the offset in the tvb
927  * @return modified offset
928  */
929 static guint
930 fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
931
932 /**
933  * ReinitializeDevice-Request ::= SEQUENCE {
934  *  reinitializedStateOfDevice  [0] ENUMERATED {
935  *      coldstart    (0),
936  *      warmstart    (1),
937  *      startbackup  (2),
938  *      endbackup    (3),
939  *      startrestore (4),
940  *      endrestore   (5),
941  *      abortrestor  (6)
942  *      },
943  *  password                    [1] CharacterString (SIZE(1..20)) OPTIONAL
944  * }
945  * @param tvb the tv buffer of the current data
946  * @param pinfo the packet info of the current data
947  * @param tree the tree to append this item to
948  * @param offset the offset in the tvb
949  * @return modified offset
950  */
951 static guint
952 fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
953
954 /**
955  * VTOpen-Request ::= SEQUENCE {
956  *  vtClass BACnetVTClass,
957  *  localVTSessionIdentifier    Unsigned8
958  * }
959  * @param tvb the tv buffer of the current data
960  * @param pinfo the packet info of the current data
961  * @param tree the tree to append this item to
962  * @param offset the offset in the tvb
963  * @return modified offset
964  */
965 static guint
966 fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
967
968 /**
969  * VTOpen-ACK ::= SEQUENCE {
970  *  remoteVTSessionIdentifier   Unsigned8
971  * }
972  * @param tvb the tv buffer of the current data
973  * @param pinfo the packet info of the current data
974  * @param tree the tree to append this item to
975  * @param offset the offset in the tvb
976  * @return modified offset
977  */
978 static guint
979 fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
980
981 /**
982  * VTClose-Request ::= SEQUENCE {
983  *  listOfRemoteVTSessionIdentifiers    SEQUENCE OF Unsigned8
984  * }
985  * @param tvb the tv buffer of the current data
986  * @param pinfo the packet info of the current data
987  * @param tree the tree to append this item to
988  * @param offset the offset in the tvb
989  * @return modified offset
990  */
991 static guint
992 fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
993
994 /**
995  * VTData-Request ::= SEQUENCE {
996  *  vtSessionIdentifier Unsigned8,
997  *  vtNewData           OCTET STRING,
998  *  vtDataFlag          Unsigned (0..1)
999  * }
1000  * @param tvb the tv buffer of the current data
1001  * @param pinfo the packet info of the current data
1002  * @param tree the tree to append this item to
1003  * @param offset the offset in the tvb
1004  * @return modified offset
1005  */
1006 static guint
1007 fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1008
1009 /**
1010  * VTData-ACK ::= SEQUENCE {
1011  *  allNewDataAccepted  [0] BOOLEAN,
1012  *  acceptedOctetCount  [1] Unsigned OPTIONAL -- present only if allNewDataAccepted = FALSE
1013  * }
1014  * @param tvb the tv buffer of the current data
1015  * @param pinfo the packet info of the current data
1016  * @param tree the tree to append this item to
1017  * @param offset the offset in the tvb
1018  * @return modified offset
1019  */
1020 static guint
1021 fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1022
1023 /**
1024  * Authenticate-Request ::= SEQUENCE {
1025  *  pseudoRandomNumber     [0] Unsigned32,
1026  *  excpectedInvokeID      [1] Unsigned8 OPTIONAL,
1027  *  operatorName           [2] CharacterString OPTIONAL,
1028  *  operatorPassword       [3] CharacterString (SIZE(1..20)) OPTIONAL,
1029  *  startEncypheredSession [4] BOOLEAN OPTIONAL
1030  * }
1031  * @param tvb the tv buffer of the current data
1032  * @param pinfo the packet info of the current data
1033  * @param tree the tree to append this item to
1034  * @param offset the offset in the tvb
1035  * @return modified offset
1036  */
1037 static guint
1038 fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1039
1040 /**
1041  * Authenticate-ACK ::= SEQUENCE {
1042  *  modifiedRandomNumber    Unsigned32,
1043  * }
1044  * @param tvb the tv buffer of the current data
1045  * @param pinfo the packet info of the current data
1046  * @param tree the tree to append this item to
1047  * @param offset the offset in the tvb
1048  * @return modified offset
1049  */
1050 static guint
1051 fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1052
1053 /**
1054  * RequestKey-Request ::= SEQUENCE {
1055  *  requestingDeviceIdentifier BACnetObjectIdentifier,
1056  *  requestingDeviceAddress    BACnetAddress,
1057  *  remoteDeviceIdentifier     BACnetObjectIdentifier,
1058  *  remoteDeviceAddress        BACnetAddress
1059  * }
1060  * @param tvb the tv buffer of the current data
1061  * @param pinfo the packet info of the current data
1062  * @param tree the tree to append this item to
1063  * @param offset the offset in the tvb
1064  * @return modified offset
1065  */
1066 static guint
1067 fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1068
1069 /**
1070  * Unconfirmed-Service-Request ::= CHOICE {
1071  * }
1072  * @param tvb the tv buffer of the current data
1073  * @param pinfo the packet info of the current data
1074  * @param tree the tree to append this item to
1075  * @param offset the offset in the tvb
1076  * @param service_choice the service choice
1077  * @return modified offset
1078  */
1079 static guint
1080 fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
1081
1082 /**
1083  * UnconfirmedCOVNotification-Request ::= SEQUENCE {
1084  *  subscriberProcessIdentifier [0] Unsigned32,
1085  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
1086  *  monitoredObjectIdentifier   [2] BACnetObjectIdentifer,
1087  *  timeRemaining               [3] unsigned,
1088  *  listOfValues                [4] SEQUENCE OF BACnetPropertyValues
1089  * }
1090  * @param tvb the tv buffer of the current data
1091  * @param pinfo the packet info of the current data
1092  * @param tree the tree to append this item to
1093  * @param offset the offset in the tvb
1094  * @return modified offset
1095  */
1096 static guint
1097 fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1098
1099 /**
1100  * UnconfirmedEventNotification-Request ::= SEQUENCE {
1101  *  ProcessIdentifier           [0] Unsigned32,
1102  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
1103  *  eventObjectIdentifier       [2] BACnetObjectIdentifer,
1104  *  timeStamp                   [3] BACnetTimeStamp,
1105  *  notificationClass           [4] unsigned,
1106  *  priority                    [5] unsigned8,
1107  *  eventType                   [6] BACnetEventType,
1108  *  messageText                 [7] CharacterString OPTIONAL,
1109  *  notifyType                  [8] BACnetNotifyType,
1110  *  ackRequired                 [9] BOOLEAN OPTIONAL,
1111  *  fromState                  [10] BACnetEventState OPTIONAL,
1112  *  toState                    [11] BACnetEventState,
1113  *  eventValues                [12] BACnetNotificationParameters OPTIONAL
1114  * }
1115  * @param tvb the tv buffer of the current data
1116  * @param pinfo the packet info of the current data
1117  * @param tree the tree to append this item to
1118  * @param offset the offset in the tvb
1119  * @return modified offset
1120  */
1121 static guint
1122 fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1123
1124 /**
1125  * I-Am-Request ::= SEQUENCE {
1126  *  aAmDeviceIdentifier BACnetObjectIdentifier,
1127  *  maxAPDULengthAccepted   Unsigned,
1128  *  segmentationSupported   BACnetSegmentation,
1129  *  vendorID    Unsigned
1130  * }
1131  * @param tvb the tv buffer of the current data
1132  * @param pinfo the packet info of the current data
1133  * @param tree the tree to append this item to
1134  * @param offset the offset in the tvb
1135  * @return modified offset
1136  */
1137 static guint
1138 fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1139
1140
1141 /**
1142  * I-Have-Request ::= SEQUENCE {
1143  *  deviceIdentifier  BACnetObjectIdentifier,
1144  *  objectIdentifier  BACnetObjectIdentifier,
1145  *  objectName        CharacterString
1146  * }
1147  * @param tvb the tv buffer of the current data
1148  * @param pinfo the packet info of the current data
1149  * @param tree the tree to append this item to
1150  * @param offset the offset in the tvb
1151  * @return modified offset
1152  */
1153 static guint
1154 fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1155
1156 /**
1157  * UnconfirmedPrivateTransfer-Request ::= SEQUENCE {
1158  *  vendorID          [0] Unsigned,
1159  *  serviceNumber     [1] Unsigned,
1160  *  serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
1161  * }
1162  * @param tvb the tv buffer of the current data
1163  * @param pinfo the packet info of the current data
1164  * @param tree the tree to append this item to
1165  * @param offset the offset in the tvb
1166  * @return modified offset
1167  */
1168 static guint
1169 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1170
1171 /**
1172  * UnconfirmedTextMessage-Request ::=  SEQUENCE {
1173  *  textMessageSourceDevice [0] BACnetObjectIdentifier,
1174  *  messageClass            [1] CHOICE {
1175  *      numeric   [0] Unsigned,
1176  *      character [1] CharacterString
1177  *      } OPTIONAL,
1178  *  messagePriority         [2] ENUMERATED {
1179  *      normal (0),
1180  *      urgent (1)
1181  *      },
1182  *  message                 [3] CharacterString
1183  * }
1184  * @param tvb the tv buffer of the current data
1185  * @param pinfo the packet info of the current data
1186  * @param tree the tree to append this item to
1187  * @param offset the offset in the tvb
1188  * @return modified offset
1189  */
1190 static guint
1191 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1192
1193 /**
1194  * TimeSynchronization-Request ::=  SEQUENCE {
1195  *  BACnetDateTime
1196  * }
1197  * @param tvb the tv buffer of the current data
1198  * @param pinfo the packet info of the current data
1199  * @param tree the tree to append this item to
1200  * @param offset the offset in the tvb
1201  * @return modified offset
1202  */
1203 static guint
1204 fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1205
1206 /**
1207  * UTCTimeSynchronization-Request ::=  SEQUENCE {
1208  *  BACnetDateTime
1209  * }
1210  * @param tvb the tv buffer of the current data
1211  * @param pinfo the packet info of the current data
1212  * @param tree the tree to append this item to
1213  * @param offset the offset in the tvb
1214  * @return modified offset
1215  */
1216 static guint
1217 fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1218
1219 /**
1220  * Who-Has-Request ::=  SEQUENCE {
1221  *  limits SEQUENCE {
1222  *      deviceInstanceRangeLowLimit  [0] Unsigned (0..4194303),
1223  *      deviceInstanceRangeHighLimit [1] Unsigned (0..4194303)
1224  *      } OPTIONAL,
1225  *  object CHOICE {
1226  *      objectIdentifier             [2] BACnetObjectIdentifier,
1227  *      objectName                   [3] CharacterString
1228  *      }
1229  * }
1230  * @param tvb the tv buffer of the current data
1231  * @param pinfo the packet info of the current data
1232  * @param tree the tree to append this item to
1233  * @param offset the offset in the tvb
1234  * @return modified offset
1235  */
1236 static guint
1237 fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1238
1239 /**
1240  * Who-Is-Request ::= SEQUENCE {
1241  *  deviceInstanceRangeLowLimit  [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1242  *  deviceInstanceRangeHighLimit [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1243  * }
1244  * @param tvb the tv buffer of the current data
1245  * @param tree the tree to append this item to
1246  * @param offset the offset in the tvb
1247  * @return modified offset
1248  */
1249 static guint
1250 fWhoIsRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1251
1252 /**
1253  * BACnet-Error ::= CHOICE {
1254  *  addListElement           [8] ChangeList-Error,
1255  *  removeListElement        [9] ChangeList-Error,
1256  *  writePropertyMultiple   [16] WritePropertyMultiple-Error,
1257  *  confirmedPrivatTransfer [18] ConfirmedPrivateTransfer-Error,
1258  *  vtClose                 [22] VTClose-Error,
1259  *  readRange               [26] ObjectAccessService-Error
1260  *                          [default] Error
1261  * }
1262  * @param tvb the tv buffer of the current data
1263  * @param pinfo the packet info of the current data
1264  * @param tree the tree to append this item to
1265  * @param offset the offset in the tvb
1266  * @param service the service
1267  * @return modified offset
1268  */
1269 static guint
1270 fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service);
1271
1272 /**
1273  * Dissect a BACnetError in a context tag
1274  *
1275  * @param tvb the tv buffer of the current data
1276  * @param pinfo the packet info of the current data
1277  * @param tree the tree to append this item to
1278  * @param offset the offset in the tvb
1279  * @return modified offset
1280  */
1281 static guint fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1282
1283 /**
1284  * ChangeList-Error ::= SEQUENCE {
1285  *    errorType                [0] Error,
1286  *    firstFailedElementNumber [1] Unsigned
1287  *    }
1288  * }
1289  * @param tvb the tv buffer of the current data
1290  * @param pinfo the packet info of the current data
1291  * @param tree the tree to append this item to
1292  * @param offset the offset in the tvb
1293  * @return modified offset
1294  */
1295 static guint
1296 fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1297
1298 /**
1299  * CreateObject-Error ::= SEQUENCE {
1300  *    errorType                [0] Error,
1301  *    firstFailedElementNumber [1] Unsigned
1302  *    }
1303  * }
1304  * @param tvb the tv buffer of the current data
1305  * @param pinfo the packet info of the current data
1306  * @param tree the tree to append this item to
1307  * @param offset the offset in the tvb
1308  * @return modified offset
1309  */
1310 static guint
1311 fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1312
1313 /**
1314  * ConfirmedPrivateTransfer-Error ::= SEQUENCE {
1315  *    errorType       [0] Error,
1316  *    vendorID        [1] Unsigned,
1317  *    serviceNumber   [2] Unsigned,
1318  *    errorParameters [3] ABSTRACT-SYNTAX.&Type OPTIONAL
1319  *    }
1320  * }
1321  * @param tvb the tv buffer of the current data
1322  * @param pinfo the packet info of the current data
1323  * @param tree the tree to append this item to
1324  * @param offset the offset in the tvb
1325  * @return modified offset
1326  */
1327 static guint
1328 fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1329
1330 /**
1331  * WritePropertyMultiple-Error ::= SEQUENCE {
1332  *    errorType               [0] Error,
1333  *    firstFailedWriteAttempt [1] Unsigned
1334  *    }
1335  * }
1336  * @param tvb the tv buffer of the current data
1337  * @param pinfo the packet info of the current data
1338  * @param tree the tree to append this item to
1339  * @param offset the offset in the tvb
1340  * @return modified offset
1341  */
1342 static guint
1343 fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1344
1345 /**
1346  * VTClose-Error ::= SEQUENCE {
1347  *    errorType                  [0] Error,
1348  *    listOfVTSessionIdentifiers [1] SEQUENCE OF Unsigned8 OPTIONAL
1349  *    }
1350  * }
1351  * @param tvb the tv buffer of the current data
1352  * @param pinfo the packet info of the current data
1353  * @param tree the tree to append this item to
1354  * @param offset the offset in the tvb
1355  * @return modified offset
1356  */
1357 static guint
1358 fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1359
1360 /**
1361  * BACnet Application Types chapter 20.2.1
1362  * @param tvb the tv buffer of the current data
1363  * @param pinfo the packet info of the current data
1364  * @param tree the tree to append this item to
1365  * @param offset the offset in the tvb
1366  * @param label the label of this item
1367  * @return modified offset
1368  */
1369 static guint
1370 fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
1371
1372 /**
1373  * BACnetActionCommand ::= SEQUENCE {
1374  *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1375  *  objectIdentifier    [1] BACnetObjectIdentifier,
1376  *  propertyIdentifier  [2] BACnetPropertyIdentifier,
1377  *  propertyArrayIndex  [3] Unsigned OPTIONAL, -- used only with array datatype
1378  *  propertyValue       [4] ABSTRACT-SYNTAX.&Type,
1379  *  priority            [5] Unsigned (1..16) OPTIONAL, -- used only when property is commandable
1380  *  postDelay           [6] Unsigned OPTIONAL,
1381  *  quitOnFailure       [7] BOOLEAN,
1382  *  writeSuccessful     [8] BOOLEAN
1383  * }
1384  * @param tvb the tv buffer of the current data
1385  * @param pinfo the packet info of the current data
1386  * @param tree the tree to append this item to
1387  * @param offset the offset in the tvb
1388  * @param tag_match the tag number
1389  * @return modified offset
1390  */
1391 static guint
1392 fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match);
1393
1394 /**
1395  * BACnetActionList ::= SEQUENCE {
1396  *  action  [0] SEQUENCE of BACnetActionCommand
1397  * }
1398  * @param tvb the tv buffer of the current data
1399  * @param pinfo the packet info of the current data
1400  * @param tree the tree to append this item to
1401  * @param offset the offset in the tvb
1402  * @return modified offset
1403  */
1404 static guint
1405 fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1406
1407 /** BACnetAddress ::= SEQUENCE {
1408  *  network-number  Unsigned16, -- A value 0 indicates the local network
1409  *  mac-address     OCTET STRING -- A string of length 0 indicates a broadcast
1410  * }
1411  * @param tvb the tv buffer of the current data
1412  * @param pinfo the packet info of the current data
1413  * @param tree the tree to append this item to
1414  * @param offset the offset in the tvb
1415  * @return modified offset
1416  */
1417 static guint
1418 fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1419
1420 /**
1421  * BACnetAddressBinding ::= SEQUENCE {
1422  *  deviceObjectID  BACnetObjectIdentifier
1423  *  deviceAddress   BacnetAddress
1424  * }
1425  * @param tvb the tv buffer of the current data
1426  * @param pinfo the packet info of the current data
1427  * @param tree the tree to append this item to
1428  * @param offset the offset in the tvb
1429  * @return modified offset
1430  */
1431 static guint
1432 fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1433
1434 /**
1435  * BACnetCalendarEntry ::= CHOICE {
1436  *  date        [0] Date,
1437  *  dateRange   [1] BACnetDateRange,
1438  *  weekNDay    [2] BacnetWeekNday
1439  * }
1440  * @param tvb the tv buffer of the current data
1441  * @param pinfo the packet info of the current data
1442  * @param tree the tree to append this item to
1443  * @param offset the offset in the tvb
1444  * @return modified offset
1445  */
1446 static guint
1447 fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1448
1449 /**
1450  * BACnetClientCOV ::= CHOICE {
1451  *  real-increment  REAL,
1452  *  default-increment   NULL
1453  * }
1454  * @param tvb the tv buffer of the current data
1455  * @param tree the tree to append this item to
1456  * @param offset the offset in the tvb
1457  * @return modified offset
1458  */
1459 static guint
1460 fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1461
1462
1463 /**
1464  * BACnetDailySchedule ::= SEQUENCE {
1465  *  day-schedule    [0] SENQUENCE OF BACnetTimeValue
1466  * }
1467  * @param tvb the tv buffer of the current data
1468  * @param pinfo the packet info of the current data
1469  * @param tree the tree to append this item to
1470  * @param offset the offset in the tvb
1471  * @return modified offset
1472  */
1473 static guint
1474 fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1475
1476 /**
1477  * BACnetWeeklySchedule ::= SEQUENCE {
1478  *  week-schedule    SENQUENCE SIZE (7) OF BACnetDailySchedule
1479  * }
1480  * @param tvb the tv buffer of the current data
1481  * @param pinfo the packet info of the current data
1482  * @param tree the tree to append this item to
1483  * @param offset the offset in the tvb
1484  * @return modified offset
1485  */
1486 static guint
1487 fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1488
1489 /**
1490  * BACnetDateRange ::= SEQUENCE {
1491  *  StartDate   Date,
1492  *  EndDate     Date
1493  * }
1494  * @param tvb the tv buffer of the current data
1495  * @param pinfo the packet info of the current data
1496  * @param tree the tree to append this item to
1497  * @param offset the offset in the tvb
1498  * @return modified offset
1499  */
1500 static guint
1501 fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1502
1503 /**
1504  * BACnetDateTime ::= SEQUENCE {
1505  *  date   Date,
1506  *  time   Time
1507  * }
1508  * @param tvb the tv buffer of the current data
1509  * @param pinfo the packet info of the current data
1510  * @param tree the tree to append this item to
1511  * @param offset the offset in the tvb
1512  * @param label the label of this item
1513  * @return modified offset
1514  */
1515 static guint
1516 fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
1517
1518 /**
1519  * BACnetDestination ::= SEQUENCE {
1520  *  validDays   BACnetDaysOfWeek,
1521  *  fromTime    Time,
1522  *  toTime      Time,
1523  *  recipient   BACnetRecipient,
1524  *  processIdentifier   Unsigned32,
1525  *  issueConfirmedNotifications BOOLEAN,
1526  *  transitions BACnetEventTransitionBits
1527  * }
1528  * @param tvb the tv buffer of the current data
1529  * @param pinfo the packet info of the current data
1530  * @param tree the tree to append this item to
1531  * @param offset the offset in the tvb
1532  * @return modified offset
1533  */
1534 static guint
1535 fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1536
1537 /**
1538  * BACnetDeviceObjectPropertyReference ::= SEQUENCE {
1539  *  objectIdentifier    [0] BACnetObjectIdentifier,
1540  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1541  *  propertyArrayIndex  [2] Unsigend OPTIONAL,
1542  *  deviceIdentifier    [3] BACnetObjectIdentifier OPTIONAL
1543  * }
1544  * @param tvb the tv buffer of the current data
1545  * @param pinfo the packet info of the current data
1546  * @param tree the tree to append this item to
1547  * @param offset the offset in the tvb
1548  * @return modified offset
1549  */
1550 static guint
1551 fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1552
1553 /**
1554  * BACnetObjectPropertyReference ::= SEQUENCE {
1555  *  objectIdentifier    [0] BACnetObjectIdentifier,
1556  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1557  *  propertyArrayIndex  [2] Unsigend OPTIONAL,
1558  * }
1559  * @param tvb the tv buffer of the current data
1560  * @param pinfo the packet info of the current data
1561  * @param tree the tree to append this item to
1562  * @param offset the offset in the tvb
1563  * @return modified offset
1564  */
1565 static guint
1566 fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1567
1568 /**
1569  * BACnetDeviceObjectReference ::= SEQUENCE {
1570  *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1571  *  objectIdentifier    [1] BACnetObjectIdentifier
1572  * }
1573  * @param tvb the tv buffer of the current data
1574  * @param pinfo the packet info of the current data
1575  * @param tree the tree to append this item to
1576  * @param offset the offset in the tvb
1577  * @return modified offset
1578  */
1579 static guint
1580 fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1581
1582 /**
1583  * BACnetEventParameter ::= CHOICE {
1584  *  change-of-bitstring             [0] SEQUENCE {
1585  *      time-delay                       [0] Unsigned,
1586  *      bitmask                          [1] BIT STRING,
1587  *      list-of-bitstring-values         [2] SEQUENCE OF BIT STRING
1588  *      },
1589  *  change-of-state                 [1] SEQUENCE {
1590  *      time-delay     [0] Unsigned,
1591  *      list-of-values [1] SEQUENCE OF BACnetPropertyStates
1592  *      },
1593  *  change-of-value                 [2] SEQUENCE {
1594  *      time-delay   [0] Unsigned,
1595  *      cov-criteria [1] CHOICE {
1596  *          bitmask                       [0] BIT STRING,
1597  *          referenced-property-increment [1] REAL
1598  *          }
1599  *      },
1600  *  command-failure                 [3] SEQUENCE {
1601  *      time-delay                       [0] Unsigned,
1602  *      feedback-property-reference      [1] BACnetDeviceObjectPropertyReference
1603  *      },
1604  *  floating-limit                  [4] SEQUENCE {
1605  *      time-delay                       [0] Unsigned,
1606  *      setpoint-reference               [1] BACnetDeviceObjectPropertyReference,
1607  *      low-diff-limit                   [2] REAL,
1608  *      high-diff-limit                  [3] REAL,
1609  *      deadband                         [4] REAL
1610  *      },
1611  *  out-of-range                    [5] SEQUENCE {
1612  *      time-delay                       [0] Unsigned,
1613  *      low-limit                        [1] REAL,
1614  *      high-limit                       [2] REAL,
1615  *      deadband                         [3] REAL
1616  *      },
1617  *  -- context tag 7 is deprecated
1618  *  change-of-life-safety           [8] SEQUENCE {
1619  *      time-delay                       [0] Unsigned,
1620  *      list-of-life-safety-alarm-values [1] SEQUENCE OF BACnetLifeSafetyState,
1621  *      list-of-alarm-values             [2] SEQUENCE OF BACnetLifeSafetyState,
1622  *      mode-property-reference          [3] BACnetDeviceObjectPropertyReference
1623  *      },
1624  *  extended                        [9] SEQUENCE {
1625  *      vendor-id                        [0] Unsigned16,
1626  *      extended-event-type              [1] Unsigned,
1627  *      parameters                       [2] SEQUENCE OF CHOICE {
1628  *          null        NULL,
1629  *          real        REAL,
1630  *          integer     Unsigned,
1631  *          boolean     BOOLEAN,
1632  *          double      Double,
1633  *          octet       OCTET STRING,
1634  *          bitstring   BIT STRING,
1635  *          enum        ENUMERATED,
1636  *          reference   [0] BACnetDeviceObjectPropertyReference
1637  *          }
1638  *      },
1639  *  buffer-ready                    [10] SEQUENCE {
1640  *      notification-threshold           [0] Unsigned,
1641  *      previous-notification-count      [1] Unsigned32
1642  *      },
1643  * unsigned-range                   [11] SEQUENCE {
1644  *      time-delay                       [0] Unsigned,
1645  *      low-limit                        [1] Unsigned,
1646  *      high-limit                       [2] Unsigned,
1647  *      }
1648  * -- context tag 12 is reserved for future addenda
1649  * access-event                     [13] SEQUENCE {
1650  *      list-of-access-events            [0] SEQUENCE OF BACnetAccessEvent,
1651  *      access-event-time-reference      [1] BACnetDeviceObjectPropertyReference
1652  *      }
1653  * double-out-of-range              [14] SEQUENCE {
1654  *      time-delay                       [0] Unsigned,
1655  *      low-limit                        [1] Double,
1656  *      high-limit                       [2] Double,
1657  *      deadband                         [3] Double
1658  *  }
1659  *  signed-out-of-range             [15] SEQUENCE {
1660  *      time-delay                       [0] Unsigned,
1661  *      low-limit                        [1] INTEGER,
1662  *      high-limit                       [2] INTEGER,
1663  *      deadband                         [3] Unsigned
1664  *  }
1665  *  unsigned-out-of-range           [16] SEQUENCE {
1666  *      time-delay                       [0] Unsigned,
1667  *      low-limit                        [1] Unsigned,
1668  *      high-limit                       [2] Unsigned,
1669  *      deadband                         [3] Unsigned
1670  *   }
1671  *  change-of-characterstring       [17] SEQUENCE {
1672  *      time-delay                       [0] Unsigned,
1673  *      list-of-alarm-values             [1] SEQUENCE OF CharacterString,
1674  *   }
1675  *  change-of-status-flags          [18] SEQUENCE {
1676  *      time-delay                       [0] Unsigned,
1677  *      selected-flags                   [1] BACnetStatusFlags
1678  *   }
1679  * }
1680  * @param tvb the tv buffer of the current data
1681  * @param tree the tree to append this item to
1682  * @param offset the offset in the tvb
1683  * @return modified offset
1684  */
1685 static guint
1686 fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1687
1688
1689
1690 /**
1691  * BACnetLogRecord ::= SEQUENCE {
1692  *  timestamp   [0] BACnetDateTime,
1693  *  logDatum    [1] CHOICE {
1694  *      log-status      [0] BACnetLogStatus,
1695  *      boolean-value   [1] BOOLEAN,
1696  *      real-value      [2] REAL,
1697  *      enum-value      [3] ENUMERATED, -- Optionally limited to 32 bits
1698  *      unsigned-value  [4] Unsigned, -- Optionally limited to 32 bits
1699  *      signed-value    [5] INTEGER, -- Optionally limited to 32 bits
1700  *      bitstring-value [6] BIT STRING, -- Optionally limited to 32 bits
1701  *      null-value      [7] NULL,
1702  *      failure         [8] Error,
1703  *      time-change     [9] REAL,
1704  *      any-value       [10] ABSTRACT-SYNTAX.&Type -- Optional
1705  *      }
1706  *  statusFlags [2] BACnetStatusFlags OPTIONAL
1707  * }
1708  * @param tvb the tv buffer of the current data
1709  * @param pinfo the packet info of the current data
1710  * @param tree the tree to append this item to
1711  * @param offset the offset in the tvb
1712  * @return modified offset
1713  */
1714 static guint
1715 fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1716
1717 /**
1718  * BACnetEventLogRecord ::= SEQUENCE {
1719  *  timestamp [0] BACnetDateTime,
1720  *  logDatum  [1] CHOICE {
1721  *      log-status   [0] BACnetLogStatus,
1722  *      notification [1] ConfirmedEventNotification-Request,
1723  *      time-change  [2] REAL,
1724  *      }
1725  * }
1726  * @param tvb the tv buffer of the current data
1727  * @param pinfo the packet info of the current data
1728  * @param tree the tree to append this item to
1729  * @param offset the offset in the tvb
1730  * @return modified offset
1731  */
1732 static guint
1733 fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1734
1735 static guint
1736 fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1737
1738 /**
1739  * BACnetNotificationParameters ::= CHOICE {
1740  *  change-of-bitstring [0] SEQUENCE {
1741  *      referenced-bitstring [0] BIT STRING,
1742  *      status-flags         [1] BACnetStatusFlags
1743  *      },
1744  *  change-of-state [1] SEQUENCE {
1745  *      new-state            [0] BACnetPropertyStatus,
1746  *      status-flags         [1] BACnetStatusFlags
1747  *      },
1748  *  change-of-value [2] SEQUENCE {
1749  *      new-value            [0] CHOICE {
1750  *          changed-bits        [0] BIT STRING,
1751  *          changed-value       [1] REAL
1752  *          },
1753  *      status-flags         [1] BACnetStatusFlags
1754  *      },
1755  *  command-failure [3] SEQUENCE {
1756  *      command-value        [0] ABSTRACT-SYNTAX.&Type, -- depends on ref property
1757  *      status-flags         [1] BACnetStatusFlags
1758  *      feedback-value       [2] ABSTRACT-SYNTAX.&Type -- depends on ref property
1759  *      },
1760  *  floating-limit [4]  SEQUENCE {
1761  *      reference-value      [0] REAL,
1762  *      status-flags         [1] BACnetStatusFlags
1763  *      setpoint-value       [2] REAL,
1764  *      error-limit          [3] REAL
1765  *      },
1766  *  out-of-range [5]    SEQUENCE {
1767  *      exceeding-value      [0] REAL,
1768  *      status-flags         [1] BACnetStatusFlags
1769  *      deadband             [2] REAL,
1770  *      exceeded-limit       [3] REAL
1771  *      },
1772  *  complex-event-type  [6] SEQUENCE OF BACnetPropertyValue,
1773  * -- complex tag 7 is deprecated
1774  *  change-of-life-safety [8]   SEQUENCE {
1775  *      new-state            [0] BACnetLifeSafetyState,
1776  *      new-mode             [1] BACnetLifeSafetyState
1777  *      status-flags         [2] BACnetStatusFlags,
1778  *      operation-expected   [3] BACnetLifeSafetyOperation
1779  *      },
1780  *  extended [9]   SEQUENCE {
1781  *      vendor-id            [0] Unsigned16,
1782  *      extended-event-type  [1] Unsigned,
1783  *      parameters           [2] SEQUENCE OF CHOICE {
1784  *          null                NULL,
1785  *          real                REAL,
1786  *          integer             Unsigned,
1787  *          boolean             BOOLEAN,
1788  *          double              Double,
1789  *          octet               OCTET STRING,
1790  *          bitstring           BIT STRING,
1791  *          enum                ENUMERATED,
1792  *          propertyValue       [0] BACnetDeviceObjectPropertyValue
1793  *          }
1794  *      },
1795  *  buffer-ready [10]    SEQUENCE {
1796  *      buffer-property      [0] BACnetDeviceObjectPropertyReference,
1797  *      previous-notification[1] Unsigned32,
1798  *      current-notification [2] BACneUnsigned32tDateTime
1799  *      },
1800  *  unsigned-range [11]    SEQUENCE {
1801  *      exceeding-value      [0] Unsigned,
1802  *      status-flags         [1] BACnetStatusFlags,
1803  *      exceeded-limit       [2] Unsigned
1804  *      },
1805  * -- context tag 12 is reserved for future addenda
1806  *  access-event [13]    SEQUENCE {
1807  *      access-event          [0] BACnetAccessEvent,
1808  *      status-flags          [1] BACnetStatusFlags,
1809  *      access-event-tag      [2] Unsigned,
1810  *      access-event-time     [3] BACnetTimeStamp,
1811  *      access-credential     [4] BACnetDeviceObjectReference,
1812  *      authentication-factor [5] BACnetAuthenticationFactor OPTIONAL
1813  *      },
1814  *  double-out-of-range [14]    SEQUENCE {
1815  *      exceeding-value      [0] Double,
1816  *      status-flags         [1] BACnetStatusFlags
1817  *      deadband             [2] Double,
1818  *      exceeded-limit       [3] Double
1819  *      },
1820  *  signed-out-of-range [15]    SEQUENCE {
1821  *      exceeding-value      [0] INTEGER,
1822  *      status-flags         [1] BACnetStatusFlags
1823  *      deadband             [2] Unsigned,
1824  *      exceeded-limit       [3] INTEGER
1825  *      },
1826  *  unsigned-out-of-range [16]    SEQUENCE {
1827  *      exceeding-value      [0] Unsigned,
1828  *      status-flags         [1] BACnetStatusFlags
1829  *      deadband             [2] Unsigned,
1830  *      exceeded-limit       [3] Unsigned
1831  *      },
1832  *  change-of-characterstring [17]    SEQUENCE {
1833  *      changed-value        [0] CharacterString,
1834  *      status-flags         [1] BACnetStatusFlags
1835  *      alarm-value          [2] CharacterString
1836  *      },
1837  *  change-of-status-flags [18]    SEQUENCE {
1838  *      present-value        [0] ABSTRACT-SYNTAX.&Type OPTIONAL,
1839  *                              -- depends on referenced property
1840  *      referenced-flags     [1] BACnetStatusFlags
1841  *      },
1842  * }
1843  * @param tvb the tv buffer of the current data
1844  * @param pinfo the packet info of the current data
1845  * @param tree the tree to append this item to
1846  * @param offset the offset in the tvb
1847  * @return modified offset
1848  */
1849 static guint
1850 fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1851
1852 /**
1853  * BACnetObjectPropertyReference ::= SEQUENCE {
1854  *  objectIdentifier    [0] BACnetObjectIdentifier,
1855  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1856  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
1857  * }
1858  * @param tvb the tv buffer of the current data
1859  * @param pinfo the packet info of the current data
1860  * @param tree the tree to append this item to
1861  * @param offset the offset in the tvb
1862  * @return modified offset
1863  */
1864 static guint
1865 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1866
1867 #if 0
1868 /**
1869  * BACnetObjectPropertyValue ::= SEQUENCE {
1870  *      objectIdentifier   [0] BACnetObjectIdentifier,
1871  *      propertyIdentifier [1] BACnetPropertyIdentifier,
1872  *      propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
1873  *                                                -- if omitted with an array the entire array is referenced
1874  *      value              [3] ABSTRACT-SYNTAX.&Type, --any datatype appropriate for the specified property
1875  *      priority           [4] Unsigned (1..16) OPTIONAL
1876  * }
1877  * @param tvb the tv buffer of the current data
1878  * @param tree the tree to append this item to
1879  * @param offset the offset in the tvb
1880  * @return modified offset
1881  */
1882 static guint
1883 fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, guint offset);
1884 #endif
1885
1886 /**
1887  * BACnetPriorityArray ::= SEQUENCE SIZE (16) OF BACnetPriorityValue
1888  * @param tvb the tv buffer of the current data
1889  * @param pinfo the packet info of the current data
1890  * @param tree the tree to append this item to
1891  * @param offset the offset in the tvb
1892  * @return modified offset
1893  */
1894 static guint
1895 fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1896
1897 static guint
1898 fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list);
1899
1900 /**
1901  * BACnetPropertyReference ::= SEQUENCE {
1902  *  propertyIdentifier  [0] BACnetPropertyIdentifier,
1903  *  propertyArrayIndex  [1] Unsigned OPTIONAL, -- used only with array datatype
1904  * }
1905  * @param tvb the tv buffer of the current data
1906  * @param pinfo the packet info of the current data
1907  * @param tree the tree to append this item to
1908  * @param offset the offset in the tvb
1909  * @return modified offset
1910  */
1911 static guint
1912 fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list);
1913
1914 /* static guint
1915 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset); */
1916
1917 static guint
1918 fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1919
1920 static guint
1921 fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1922
1923 /**
1924  * BACnetPropertyValue ::= SEQUENCE {
1925  *      PropertyIdentifier [0] BACnetPropertyIdentifier,
1926  *      propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatypes
1927  *                                                -- if omitted with an array the entire array is referenced
1928  *      value              [2] ABSTRACT-SYNTAX.&Type, -- any datatype appropriate for the specified property
1929  *      priority           [3] Unsigned (1..16) OPTIONAL -- used only when property is commandable
1930  * }
1931  * @param tvb the tv buffer of the current data
1932  * @param pinfo the packet info of the current data
1933  * @param tree the tree to append this item to
1934  * @param offset the offset in the tvb
1935  * @return modified offset
1936  */
1937 static guint
1938 fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1939
1940 static guint
1941 fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset);
1942
1943 /**
1944  * BACnet Application PDUs chapter 21
1945  * BACnetRecipient::= CHOICE {
1946  *  device  [0] BACnetObjectIdentifier
1947  *  address [1] BACnetAddress
1948  * }
1949  * @param tvb the tv buffer of the current data
1950  * @param pinfo the packet info of the current data
1951  * @param tree the tree to append this item to
1952  * @param offset the offset in the tvb
1953  * @return modified offset
1954  */
1955 static guint
1956 fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1957
1958 /**
1959  * BACnet Application PDUs chapter 21
1960  * BACnetRecipientProcess::= SEQUENCE {
1961  *  recipient   [0] BACnetRecipient
1962  *  processID   [1] Unsigned32
1963  * }
1964  * @param tvb the tv buffer of the current data
1965  * @param pinfo the packet info of the current data
1966  * @param tree the tree to append this item to
1967  * @param offset the offset in the tvb
1968  * @return modified offset
1969  */
1970 static guint
1971 fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1972
1973 static guint
1974 fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1975
1976 #if 0
1977 /**
1978  * BACnetSessionKey ::= SEQUENCE {
1979  *  sessionKey  OCTET STRING (SIZE(8)), -- 56 bits for key, 8 bits for checksum
1980  *  peerAddress BACnetAddress
1981  * }
1982  * @param tvb the tv buffer of the current data
1983  * @param tree the tree to append this item to
1984  * @param offset the offset in the tvb
1985  * @return modified offset
1986  * @todo check if checksum is displayed correctly
1987  */
1988 static guint
1989 fSessionKey(tvbuff_t *tvb, proto_tree *tree, guint offset);
1990 #endif
1991
1992 /**
1993  * BACnetSpecialEvent ::= SEQUENCE {
1994  *  period      CHOICE {
1995  *      calendarEntry       [0] BACnetCalendarEntry,
1996  *      calendarRefernce    [1] BACnetObjectIdentifier
1997  *      },
1998  *      listOfTimeValues    [2] SEQUENCE OF BACnetTimeValue,
1999  *      eventPriority       [3] Unsigned (1..16)
2000  * }
2001  * @param tvb the tv buffer of the current data
2002  * @param pinfo the packet info of the current data
2003  * @param tree the tree to append this item to
2004  * @param offset the offset in the tvb
2005  * @return modified offset
2006  */
2007 static guint
2008 fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2009
2010 /**
2011  * BACnetTimeStamp ::= CHOICE {
2012  *  time            [0] Time,
2013  *  sequenceNumber  [1] Unsigned (0..65535),
2014  *  dateTime        [2] BACnetDateTime
2015  * }
2016  * @param tvb the tv buffer of the current data
2017  * @param pinfo the packet info of the current data
2018  * @param tree the tree to append this item to
2019  * @param offset the offset in the tvb
2020  * @param label the label of this item
2021  * @return modified offset
2022  */
2023 static guint
2024 fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2025
2026 static guint
2027 fEventTimeStamps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2028
2029 /**
2030  * BACnetTimeValue ::= SEQUENCE {
2031  *  time    Time,
2032  *  value   ABSTRACT-SYNTAX.&Type -- any primitive datatype, complex types cannot be decoded
2033  * }
2034  * @param tvb the tv buffer of the current data
2035  * @param pinfo the packet info of the current data
2036  * @param tree the tree to append this item to
2037  * @param offset the offset in the tvb
2038  * @return modified offset
2039  */
2040 static guint
2041 fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2042
2043 #if 0
2044 /**
2045  * BACnetVTSession ::= SEQUENCE {
2046  *  local-vtSessionID   Unsigned8,
2047  *  remote-vtSessionID  Unsigned8,
2048  *  remote-vtAddress    BACnetAddress
2049  * }
2050  * @param tvb the tv buffer of the current data
2051  * @param tree the tree to append this item to
2052  * @param offset the offset in the tvb
2053  * @return modified offset
2054  */
2055 static guint
2056 fVTSession(tvbuff_t *tvb, proto_tree *tree, guint offset);
2057 #endif
2058
2059 /**
2060  * BACnetWeekNDay ::= OCTET STRING (SIZE (3))
2061  * -- first octet month (1..12) January = 1, X'FF' = any month
2062  * -- second octet weekOfMonth where: 1 = days numbered 1-7
2063  * -- 2 = days numbered 8-14
2064  * -- 3 = days numbered 15-21
2065  * -- 4 = days numbered 22-28
2066  * -- 5 = days numbered 29-31
2067  * -- 6 = last 7 days of this month
2068  * -- X'FF' = any week of this month
2069  * -- third octet dayOfWeek (1..7) where 1 = Monday
2070  * -- 7 = Sunday
2071  * -- X'FF' = any day of week
2072  * @param tvb the tv buffer of the current data
2073  * @param pinfo the packet info of the current data
2074  * @param tree the tree to append this item to
2075  * @param offset the offset in the tvb
2076  * @return modified offset
2077  */
2078 static guint
2079 fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2080
2081 /**
2082  * ReadAccessResult ::= SEQUENCE {
2083  *  objectIdentifier            [0] BACnetObjectIdentifier,
2084  *  listOfResults               [1] SEQUENCE OF SEQUENCE {
2085  *      propertyIdentifier      [2] BACnetPropertyIdentifier,
2086  *      propertyArrayIndex      [3] Unsigned OPTIONAL, -- used only with array datatype if omitted with an array the entire array is referenced
2087  *      readResult  CHOICE {
2088  *          propertyValue       [4] ABSTRACT-SYNTAX.&Type,
2089  *          propertyAccessError [5] Error
2090  *      }
2091  *  } OPTIONAL
2092  * }
2093  * @param tvb the tv buffer of the current data
2094  * @param pinfo the packet info of the current data
2095  * @param tree the tree to append this item to
2096  * @param offset the offset in the tvb
2097  * @return modified offset
2098  */
2099 static guint
2100 fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2101
2102 /**
2103  * ReadAccessSpecification ::= SEQUENCE {
2104  *  objectIdentifier         [0] BACnetObjectIdentifier,
2105  *  listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference
2106  * }
2107  * @param tvb the tv buffer of the current data
2108  * @param pinfo the packet info of the current data
2109  * @param subtree the subtree to append this item to
2110  * @param offset the offset in the tvb
2111  * @return modified offset
2112  */
2113 static guint
2114 fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2115
2116 /**
2117  * WriteAccessSpecification ::= SEQUENCE {
2118  *  objectIdentifier [0] BACnetObjectIdentifier,
2119  *  listOfProperty   [1] SEQUENCE OF BACnetPropertyValue
2120  * }
2121  * @param tvb the tv buffer of the current data
2122  * @param pinfo the packet info of the current data
2123  * @param subtree the sub tree to append this item to
2124  * @param offset the offset in the tvb
2125  * @return modified offset
2126  */
2127 static guint
2128 fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2129
2130
2131 /********************************************************* Helper functions *******************************************/
2132
2133 /**
2134  * extracts the tag number from the tag header.
2135  * @param tvb the tv buffer of the current data "TestyVirtualBuffer"
2136  * @param offset the offset in the tvb in actual tvb
2137  * @return Tag Number corresponding to BACnet 20.2.1.2 Tag Number
2138  */
2139 static guint
2140 fTagNo(tvbuff_t *tvb, guint offset);
2141
2142 /**
2143  * splits Tag Header coresponding to 20.2.1 General Rules For BACnet Tags
2144  * @param tvb the tv buffer of the current data = "TestyVirtualBuffer"
2145  * @param pinfo the packet info of the current data = packet info
2146  * @param offset the offset in the tvb = offset in actual tvb
2147  * @return tag_no BACnet 20.2.1.2 Tag Number
2148  * @return class_tag BACnet 20.2.1.1 Class
2149  * @return lvt BACnet 20.2.1.3 Length/Value/Type
2150  * @return offs = length of this header
2151  */
2152
2153 static guint
2154 fTagHeader(tvbuff_t *tvb, packet_info *pinfo, guint offset, guint8 *tag_no, guint8* class_tag, guint32 *lvt);
2155
2156
2157 /**
2158  * adds processID with max 32Bit unsigned Integer Value to tree
2159  * @param tvb the tv buffer of the current data
2160  * @param pinfo the packet info of the current data
2161  * @param tree the tree to append this item to
2162  * @param offset the offset in the tvb
2163  * @return modified offset
2164  */
2165 static guint
2166 fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2167
2168 /**
2169  * adds timeSpan with max 32Bit unsigned Integer Value to tree
2170  * @param tvb the tv buffer of the current data
2171  * @param pinfo the packet info of the current data
2172  * @param tree the tree to append this item to
2173  * @param offset the offset in the tvb
2174  * @return modified offset
2175  */
2176 static guint
2177 fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2178
2179 /**
2180  * BACnet Application PDUs chapter 21
2181  * BACnetPropertyIdentifier::= ENUMERATED {
2182  *   @see bacapp_property_identifier
2183  * }
2184  * @param tvb the tv buffer of the current data
2185  * @param pinfo the packet info of the current data
2186  * @param tree the tree to append this item to
2187  * @param offset the offset in the tvb
2188  * @return modified offset
2189  */
2190 static guint
2191 fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2192
2193 /**
2194  * BACnet Application PDUs chapter 21
2195  * BACnetPropertyArrayIndex::= ENUMERATED {
2196  *   @see bacapp_property_array_index
2197  * }
2198  * @param tvb the tv buffer of the current data
2199  * @param pinfo the packet info of the current data
2200  * @param tree the tree to append this item to
2201  * @param offset the offset in the tvb
2202  * @return modified offset
2203  */
2204 static guint
2205 fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2206
2207 /**
2208  * listOfEventSummaries ::= SEQUENCE OF SEQUENCE {
2209  *  objectIdentifier        [0] BACnetObjectIdentifier,
2210  *  eventState              [1] BACnetEventState,
2211  *  acknowledgedTransitions [2] BACnetEventTransitionBits,
2212  *  eventTimeStamps         [3] SEQURNCE SIZE (3) OF BACnetTimeStamps,
2213  *  notifyType              [4] BACnetNotifyType,
2214  *  eventEnable             [5] BACnetEventTransitionBits,
2215  *  eventPriorities         [6] SEQUENCE SIZE (3) OF Unsigned
2216  * }
2217  * @param tvb the tv buffer of the current data
2218  * @param pinfo the packet info of the current data
2219  * @param tree the tree to append this item to
2220  * @param offset the offset in the tvb
2221  * @return modified offset
2222  */
2223 static guint
2224 flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2225
2226 /**
2227  * SelectionCriteria ::= SEQUENCE {
2228  *  propertyIdentifier [0] BACnetPropertyIdentifier,
2229  *  propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatype
2230  *  relationSpecifier  [2] ENUMERATED { bacapp_relationSpecifier },
2231  *  comparisonValue    [3] ABSTRACT-SYNTAX.&Type
2232  * }
2233  * @param tvb the tv buffer of the current data
2234  * @param pinfo the packet info of the current data
2235  * @param tree the tree to append this item to
2236  * @param offset the offset in the tvb
2237  * @return modified offset
2238  */
2239 static guint
2240 fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2241
2242 /**
2243  * objectSelectionCriteria ::= SEQUENCE {
2244  *  selectionLogic          [0] ENUMERATED { bacapp_selectionLogic },
2245  *  listOfSelectionCriteria [1] SelectionCriteria
2246  * }
2247  * @param tvb the tv buffer of the current data
2248  * @param pinfo the packet info of the current data
2249  * @param subtree the sub tree to append this item to
2250  * @param offset the offset in the tvb
2251  * @return modified offset
2252  */
2253 static guint
2254 fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2255
2256 /**
2257  * BACnet-Error ::= SEQUENCE {
2258  *    error-class ENUMERATED {},
2259  *    error-code  ENUMERATED {}
2260  *    }
2261  * }
2262  * @param tvb the tv buffer of the current data
2263  * @param pinfo the packet info of the current data
2264  * @param tree the tree to append this item to
2265  * @param offset the offset in the tvb
2266  * @return modified offset
2267  */
2268 static guint
2269 fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2270
2271 /**
2272  * Generic handler for context tagged values.  Mostly for handling
2273  * vendor-defined properties and services.
2274  * @param tvb the tv buffer of the current data
2275  * @param pinfo the packet info of the current data
2276  * @param tree the tree to append this item to
2277  * @param offset the offset in the tvb
2278  * @return modified offset
2279  * @todo beautify this ugly construct
2280  */
2281 static guint
2282 fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2283
2284 /**
2285  * realizes some ABSTRACT-SYNTAX.&Type
2286  * @param tvb the tv buffer of the current data
2287  * @param pinfo the packet info of the current data
2288  * @param tree the tree to append this item to
2289  * @param offset the offset in the tvb
2290  * @return modified offset
2291  * @todo beautify this ugly construct
2292  */
2293 static guint
2294 fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2295
2296
2297 static guint
2298 fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label,
2299     const value_string *src);
2300
2301 /**
2302  * register_bacapp
2303  */
2304 void
2305 proto_register_bacapp(void);
2306
2307 /**
2308  * proto_reg_handoff_bacapp
2309  */
2310 void
2311 proto_reg_handoff_bacapp(void);
2312
2313 /* <<<< formerly bacapp.h */
2314
2315 /* reassembly table for segmented messages */
2316 static reassembly_table msg_reassembly_table;
2317
2318 /* some necessary forward function prototypes */
2319 static guint
2320 fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
2321     const gchar *label, const value_string *vs);
2322
2323 static const char *bacapp_unknown_service_str = "unknown service";  /* Usage: no format specifiers */
2324 static const char *ASHRAE_Reserved_Fmt = "(%d) Reserved for Use by ASHRAE";
2325 static const char *Vendor_Proprietary_Fmt = "(%d) Vendor Proprietary Value";
2326
2327 static const value_string
2328 BACnetTypeName[] = {
2329     { 0, "Confirmed-REQ"},
2330     { 1, "Unconfirmed-REQ"},
2331     { 2, "Simple-ACK"},
2332     { 3, "Complex-ACK"},
2333     { 4, "Segment-ACK"},
2334     { 5, "Error"},
2335     { 6, "Reject"},
2336     { 7, "Abort"},
2337     { 0, NULL }
2338 };
2339
2340 static const true_false_string segments_follow = {
2341     "Segmented Request",
2342     "Unsegmented Request"
2343 };
2344
2345 static const true_false_string more_follow = {
2346     "More Segments Follow",
2347     "No More Segments Follow"
2348 };
2349
2350 static const true_false_string segmented_accept = {
2351     "Segmented Response accepted",
2352     "Segmented Response not accepted"
2353 };
2354
2355 static const true_false_string
2356 BACnetTagClass = {
2357     "Context Specific Tag",
2358     "Application Tag"
2359 };
2360
2361 static const value_string
2362 BACnetMaxSegmentsAccepted [] = {
2363     { 0,  "Unspecified"},
2364     { 1,  "2 segments"},
2365     { 2,  "4 segments"},
2366     { 3,  "8 segments"},
2367     { 4, "16 segments"},
2368     { 5, "32 segments"},
2369     { 6, "64 segments"},
2370     { 7, "Greater than 64 segments"},
2371     { 0, NULL }
2372 };
2373
2374 static const value_string
2375 BACnetMaxAPDULengthAccepted [] = {
2376     {  0, "Up to MinimumMessageSize (50 octets)"},
2377     {  1, "Up to 128 octets"},
2378     {  2, "Up to 206 octets (fits in a LonTalk frame)"},
2379     {  3, "Up to 480 octets (fits in an ARCNET frame)"},
2380     {  4, "Up to 1024 octets"},
2381     {  5, "Up to 1476 octets (fits in an ISO 8802-3 frame)"},
2382     {  6, "reserved by ASHRAE"},
2383     {  7, "reserved by ASHRAE"},
2384     {  8, "reserved by ASHRAE"},
2385     {  9, "reserved by ASHRAE"},
2386     { 10, "reserved by ASHRAE"},
2387     { 11, "reserved by ASHRAE"},
2388     { 12, "reserved by ASHRAE"},
2389     { 13, "reserved by ASHRAE"},
2390     { 14, "reserved by ASHRAE"},
2391     { 15, "reserved by ASHRAE"},
2392     { 0, NULL}
2393 };
2394
2395 static const value_string
2396 BACnetRejectReason [] = {
2397     {0, "other"},
2398     {1, "buffer-overflow"},
2399     {2, "inconsistent-parameters"},
2400     {3, "invalid-parameter-data-type"},
2401     {4, "invalid-tag"},
2402     {5, "missing-required-parameter"},
2403     {6, "parameter-out-of-range"},
2404     {7, "too-many-arguments"},
2405     {8, "undefined-enumeration"},
2406     {9, "unrecognized-service"},
2407     {0, NULL}
2408 };
2409
2410 static const value_string
2411 BACnetRestartReason [] = {
2412     { 0, "unknown"},
2413     { 1, "coldstart"},
2414     { 2, "warmstart"},
2415     { 3, "detected-power-lost"},
2416     { 4, "detected-powered-off"},
2417     { 5, "hardware-watchdog"},
2418     { 6, "software-watchdog"},
2419     { 7, "suspended"},
2420     { 0, NULL}
2421 };
2422
2423 static const value_string
2424 BACnetApplicationTagNumber [] = {
2425     {  0, "Null"},
2426     {  1, "Boolean"},
2427     {  2, "Unsigned Integer"},
2428     {  3, "Signed Integer (2's complement notation)"},
2429     {  4, "Real (ANSI/IEE-754 floating point)"},
2430     {  5, "Double (ANSI/IEE-754 double precision floating point)"},
2431     {  6, "Octet String"},
2432     {  7, "Character String"},
2433     {  8, "Bit String"},
2434     {  9, "Enumerated"},
2435     { 10, "Date"},
2436     { 11, "Time"},
2437     { 12, "BACnetObjectIdentifier"},
2438     { 13, "reserved by ASHRAE"},
2439     { 14, "reserved by ASHRAE"},
2440     { 15, "reserved by ASHRAE"},
2441     { 0,  NULL}
2442 };
2443
2444 static const value_string
2445 BACnetAction [] = {
2446     { 0, "direct"},
2447     { 1, "reverse"},
2448     { 0, NULL}
2449 };
2450
2451 static const value_string
2452 BACnetAccessEvent [] = {
2453     {  0, "none"},
2454     {  1, "granted"},
2455     {  2, "muster"},
2456     {  3, "passback-detected"},
2457     {  4, "duress"},
2458     {  5, "trace"},
2459     {  6, "lockout-max-attempts"},
2460     {  7, "lockout-other"},
2461     {  8, "lockout-relinquished"},
2462     {  9, "lockout-by-higher-priority"},
2463     { 10, "out-of-service"},
2464     { 11, "out-of-service-relinquished"},
2465     { 12, "accompaniment-by"},
2466     { 13, "authentication-factor-read"},
2467     { 14, "authorization-delayed"},
2468     { 15, "verification-required"},
2469     /* Enumerated values 128-511 are used for events
2470      * which indicate that access has been denied. */
2471     { 128, "denied-deny-all"},
2472     { 129, "denied-unknown-credential"},
2473     { 130, "denied-authentication-unavailable"},
2474     { 131, "denied-authentication-factor-timeout"},
2475     { 132, "denied-incorrect-authentication-factor"},
2476     { 133, "denied-zone-no-access-rights"},
2477     { 134, "denied-point-no-access-rights"},
2478     { 135, "denied-no-access-rights"},
2479     { 136, "denied-out-of-time-range"},
2480     { 137, "denied-threat-level"},
2481     { 138, "denied-passback"},
2482     { 139, "denied-unexpected-location-usage"},
2483     { 140, "denied-max-attempts"},
2484     { 141, "denied-lower-occupancy-limit"},
2485     { 142, "denied-upper-occupancy-limit"},
2486     { 143, "denied-authentication-factor-lost"},
2487     { 144, "denied-authentication-factor-stolen"},
2488     { 145, "denied-authentication-factor-damaged"},
2489     { 146, "denied-authentication-factor-destroyed"},
2490     { 147, "denied-authentication-factor-disabled"},
2491     { 148, "denied-authentication-factor-error"},
2492     { 149, "denied-credential-unassigned"},
2493     { 150, "denied-credential-not-provisioned"},
2494     { 151, "denied-credential-not-yet-active"},
2495     { 152, "denied-credential-expired"},
2496     { 153, "denied-credential-manual-disable"},
2497     { 154, "denied-credential-lockout"},
2498     { 155, "denied-credential-max-days"},
2499     { 156, "denied-credential-max-uses"},
2500     { 157, "denied-credential-inactivity"},
2501     { 158, "denied-credential-disabled"},
2502     { 159, "denied-no-accompaniment"},
2503     { 160, "denied-incorrect-accompaniment"},
2504     { 161, "denied-lockout"},
2505     { 162, "denied-verification-failed"},
2506     { 163, "denied-verification-timeout"},
2507     { 164, "denied-other"},
2508     { 0,  NULL}
2509 /* Enumerated values 0-512 are reserved for definition by ASHRAE.
2510    Enumerated values 512-65535 may be used by others subject to
2511    procedures and constraints described in Clause 23. */
2512 };
2513
2514 static const value_string
2515 BACnetFileAccessMethod [] = {
2516     { 0, "record-access"},
2517     { 1, "stream-access"},
2518     { 0, NULL}
2519 };
2520
2521 /* For some reason, BACnet defines the choice parameter
2522    in the file read and write services backwards from the
2523    BACnetFileAccessMethod enumeration.
2524 */
2525 static const value_string
2526 BACnetFileAccessOption [] = {
2527     { 0, "stream access"},
2528     { 1, "record access"},
2529     { 0, NULL}
2530 };
2531
2532 static const value_string
2533 BACnetFileStartOption [] = {
2534     { 0, "File Start Position: "},
2535     { 1, "File Start Record: "},
2536     { 0, NULL}
2537 };
2538
2539 static const value_string
2540 BACnetFileRequestCount [] = {
2541     { 0, "Requested Octet Count: "},
2542     { 1, "Requested Record Count: "},
2543     { 0, NULL}
2544 };
2545
2546 static const value_string
2547 BACnetFileWriteInfo [] = {
2548     { 0, "File Data: "},
2549     { 1, "Record Count: "},
2550     { 0, NULL}
2551 };
2552
2553 static const value_string
2554 BACnetAbortReason [] = {
2555     { 0, "other"},
2556     { 1, "buffer-overflow"},
2557     { 2, "invalid-apdu-in-this-state"},
2558     { 3, "preempted-by-higher-priority-task"},
2559     { 4, "segmentation-not-supported"},
2560     { 0, NULL}
2561 };
2562
2563 static const value_string
2564 BACnetLifeSafetyMode [] = {
2565     {  0, "off"},
2566     {  1, "on"},
2567     {  2, "test"},
2568     {  3, "manned"},
2569     {  4, "unmanned"},
2570     {  5, "armed"},
2571     {  6, "disarmed"},
2572     {  7, "prearmed"},
2573     {  8, "slow"},
2574     {  9, "fast"},
2575     { 10, "disconnected"},
2576     { 11, "enabled"},
2577     { 12, "disabled"},
2578     { 13, "atomic-release-disabled"},
2579     { 14, "default"},
2580     { 0,  NULL}
2581 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2582    Enumerated values 256-65535 may be used by others subject to
2583    procedures and constraints described in Clause 23. */
2584 };
2585
2586 static const value_string
2587 BACnetLifeSafetyOperation [] = {
2588     { 0, "none"},
2589     { 1, "silence"},
2590     { 2, "silence-audible"},
2591     { 3, "silence-visual"},
2592     { 4, "reset"},
2593     { 5, "reset-alarm"},
2594     { 6, "reset-fault"},
2595     { 7, "unsilence"},
2596     { 8, "unsilence-audible"},
2597     { 9, "unsilence-visual"},
2598     { 0, NULL}
2599 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
2600    Enumerated values 64-65535 may be used by others subject to
2601    procedures and constraints described in Clause 23. */
2602 };
2603
2604 #if 0
2605 static const value_string
2606 BACnetLimitEnable [] = {
2607     { 0, "lowLimitEnable"},
2608     { 1, "highLimitEnable"},
2609     { 0, NULL}
2610 };
2611 #endif
2612
2613 static const value_string
2614 BACnetLifeSafetyState [] = {
2615     {  0, "quiet"},
2616     {  1, "pre-alarm"},
2617     {  2, "alarm"},
2618     {  3, "fault"},
2619     {  4, "fault-pre-alarm"},
2620     {  5, "fault-alarm"},
2621     {  6, "not-ready"},
2622     {  7, "active"},
2623     {  8, "tamper"},
2624     {  9, "test-alarm"},
2625     { 10, "test-active"},
2626     { 11, "test-fault"},
2627     { 12, "test-fault-alarm"},
2628     { 13, "holdup"},
2629     { 14, "duress"},
2630     { 15, "tamper-alarm"},
2631     { 16, "abnormal"},
2632     { 17, "emergency-power"},
2633     { 18, "delayed"},
2634     { 19, "blocked"},
2635     { 20, "local-alarm"},
2636     { 21, "general-alarm"},
2637     { 22, "supervisory"},
2638     { 23, "test-supervisory"},
2639     { 0,  NULL}
2640 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2641    Enumerated values 256-65535 may be used by others subject to
2642    procedures and constraints described in Clause 23. */
2643 };
2644
2645 static const value_string
2646 BACnetConfirmedServiceChoice [] = {
2647     {  0, "acknowledgeAlarm"},
2648     {  1, "confirmedCOVNotification"},
2649     {  2, "confirmedEventNotification"},
2650     {  3, "getAlarmSummary"},
2651     {  4, "getEnrollmentSummary"},
2652     {  5, "subscribeCOV"},
2653     {  6, "atomicReadFile"},
2654     {  7, "atomicWriteFile"},
2655     {  8, "addListElement"},
2656     {  9, "removeListElement"},
2657     { 10, "createObject"},
2658     { 11, "deleteObject"},
2659     { 12, "readProperty"},
2660     { 13, "readPropertyConditional"},
2661     { 14, "readPropertyMultiple"},
2662     { 15, "writeProperty"},
2663     { 16, "writePropertyMultiple"},
2664     { 17, "deviceCommunicationControl"},
2665     { 18, "confirmedPrivateTransfer"},
2666     { 19, "confirmedTextMessage"},
2667     { 20, "reinitializeDevice"},
2668     { 21, "vtOpen"},
2669     { 22, "vtClose"},
2670     { 23, "vtData"},
2671     { 24, "authenticate"},
2672     { 25, "requestKey"},
2673     { 26, "readRange"},
2674     { 27, "lifeSafetyOperation"},
2675     { 28, "subscribeCOVProperty"},
2676     { 29, "getEventInformation"},
2677     { 30, "reserved by ASHRAE"},
2678     { 0,  NULL}
2679 };
2680
2681 static const value_string
2682 BACnetReliability [] = {
2683     {  0, "no-fault-detected"},
2684     {  1, "no-sensor"},
2685     {  2, "over-range"},
2686     {  3, "under-range"},
2687     {  4, "open-loop"},
2688     {  5, "shorted-loop"},
2689     {  6, "no-output"},
2690     {  7, "unreliable-other"},
2691     {  8, "process-error"},
2692     {  9, "multi-state-fault"},
2693     { 10, "configuration-error"},
2694     /* enumeration value 11 is reserved for a future addendum */
2695     { 12, "communication-failure"},
2696     { 13, "member-fault"},
2697     { 0,  NULL}
2698 };
2699
2700 static const value_string
2701 BACnetUnconfirmedServiceChoice [] = {
2702     { 0, "i-Am"},
2703     { 1, "i-Have"},
2704     { 2, "unconfirmedCOVNotification"},
2705     { 3, "unconfirmedEventNotification"},
2706     { 4, "unconfirmedPrivateTransfer"},
2707     { 5, "unconfirmedTextMessage"},
2708     { 6, "timeSynchronization"},
2709     { 7, "who-Has"},
2710     { 8, "who-Is"},
2711     { 9, "utcTimeSynchronization"},
2712     { 0, NULL}
2713 };
2714
2715 #if 0
2716 static const value_string
2717 BACnetUnconfirmedServiceRequest [] = {
2718     { 0, "i-Am-Request"},
2719     { 1, "i-Have-Request"},
2720     { 2, "unconfirmedCOVNotification-Request"},
2721     { 3, "unconfirmedEventNotification-Request"},
2722     { 4, "unconfirmedPrivateTransfer-Request"},
2723     { 5, "unconfirmedTextMessage-Request"},
2724     { 6, "timeSynchronization-Request"},
2725     { 7, "who-Has-Request"},
2726     { 8, "who-Is-Request"},
2727     { 9, "utcTimeSynchonization-Request"},
2728     { 0, NULL}
2729 };
2730 #endif
2731
2732 static const value_string
2733 BACnetObjectType [] = {
2734     {  0, "analog-input"},
2735     {  1, "analog-output"},
2736     {  2, "analog-value"},
2737     {  3, "binary-input"},
2738     {  4, "binary-output"},
2739     {  5, "binary-value"},
2740     {  6, "calendar"},
2741     {  7, "command"},
2742     {  8, "device"},
2743     {  9, "event-enrollment"},
2744     { 10, "file"},
2745     { 11, "group"},
2746     { 12, "loop"},
2747     { 13, "multi-state-input"},
2748     { 14, "multi-state-output"},
2749     { 15, "notification-class"},
2750     { 16, "program"},
2751     { 17, "schedule"},
2752     { 18, "averaging"},
2753     { 19, "multi-state-value"},
2754     { 20, "trend-log"},
2755     { 21, "life-safety-point"},
2756     { 22, "life-safety-zone"},
2757     { 23, "accumulator"},
2758     { 24, "pulse-converter"},
2759     { 25, "event-log"},
2760     { 26, "global-group"},
2761     { 27, "trend-log-multiple"},
2762     { 28, "load-control"},
2763     { 29, "structured-view"},
2764     { 30, "access-door"},     /* 30-37 added with addanda 135-2008j */
2765     /* value 31 is unassigned */
2766     { 32, "access-credential"},
2767     { 33, "access-point"},
2768     { 34, "access-rights"},
2769     { 35, "access-user"},
2770     { 36, "access-zone"},
2771     { 37, "credential-data-input"},
2772     { 38, "network-security"},
2773     { 39, "bitstring-value"},     /* 39-50 added with addenda 135-2008w */
2774     { 40, "characterstring-value"},
2775     { 41, "date-pattern-value"},
2776     { 42, "date-value"},
2777     { 43, "datetime-pattern-value"},
2778     { 44, "datetime-value"},
2779     { 45, "integer-value"},
2780     { 46, "large-analog-value"},
2781     { 47, "octetstring-value"},
2782     { 48, "positive-integer-value"},
2783     { 49, "time-pattern-value"},
2784     { 50, "time-value"},
2785     { 0,  NULL}
2786 /* Enumerated values 0-127 are reserved for definition by ASHRAE.
2787    Enumerated values 128-1023 may be used by others subject to
2788    the procedures and constraints described in Clause 23. */
2789 };
2790
2791 static const value_string
2792 BACnetEngineeringUnits [] = {
2793     {   0, "Sq Meters"},
2794     {   1, "Sq Feet"},
2795     {   2, "Milliamperes"},
2796     {   3, "Amperes"},
2797     {   4, "Ohms"},
2798     {   5, "Volts"},
2799     {   6, "Kilovolts"},
2800     {   7, "Megavolts"},
2801     {   8, "Volt Amperes"},
2802     {   9, "Kilovolt Amperes"},
2803     {  10, "Megavolt Amperes"},
2804     {  11, "Volt Amperes Reactive"},
2805     {  12, "Kilovolt Amperes Reactive"},
2806     {  13, "Megavolt Amperes Reactive"},
2807     {  14, "Degrees Phase"},
2808     {  15, "Power Factor"},
2809     {  16, "Joules"},
2810     {  17, "Kilojoules"},
2811     {  18, "Watt Hours"},
2812     {  19, "Kilowatt Hours"},
2813     {  20, "BTUs"},
2814     {  21, "Therms"},
2815     {  22, "Ton Hours"},
2816     {  23, "Joules Per Kg Dry Air"},
2817     {  24, "BTUs Per Pound Dry Air"},
2818     {  25, "Cycles Per Hour"},
2819     {  26, "Cycles Per Minute"},
2820     {  27, "Hertz"},
2821     {  28, "Grams Of Water Per Kilogram Dry Air"},
2822     {  29, "Relative Humidity"},
2823     {  30, "Millimeters"},
2824     {  31, "Meters"},
2825     {  32, "Inches"},
2826     {  33, "Feed"},
2827     {  34, "Watts Per Sq Foot"},
2828     {  35, "Watts Per Sq meter"},
2829     {  36, "Lumens"},
2830     {  37, "Lux"},
2831     {  38, "Foot Candles"},
2832     {  39, "Kilograms"},
2833     {  40, "Pounds Mass"},
2834     {  41, "Tons"},
2835     {  42, "Kgs per Second"},
2836     {  43, "Kgs Per Minute"},
2837     {  44, "Kgs Per Hour"},
2838     {  45, "Pounds Mass Per Minute"},
2839     {  46, "Pounds Mass Per Hour"},
2840     {  47, "Watt"},
2841     {  48, "Kilowatts"},
2842     {  49, "Megawatts"},
2843     {  50, "BTUs Per Hour"},
2844     {  51, "Horsepower"},
2845     {  52, "Tons Refrigeration"},
2846     {  53, "Pascals"},
2847     {  54, "Kilopascals"},
2848     {  55, "Bars"},
2849     {  56, "Pounds Force Per Square Inch"},
2850     {  57, "Centimeters Of Water"},
2851     {  58, "Inches Of Water"},
2852     {  59, "Millimeters Of Mercury"},
2853     {  60, "Centimeters Of Mercury"},
2854     {  61, "Inches Of Mercury"},
2855     {  62, "Degrees Celsius"},
2856     {  63, "Degrees Kelvin"},
2857     {  64, "Degrees Fahrenheit"},
2858     {  65, "Degree Days Celsius"},
2859     {  66, "Degree Days Fahrenheit"},
2860     {  67, "Years"},
2861     {  68, "Months"},
2862     {  69, "Weeks"},
2863     {  70, "Days"},
2864     {  71, "Hours"},
2865     {  72, "Minutes"},
2866     {  73, "Seconds"},
2867     {  74, "Meters Per Second"},
2868     {  75, "Kilometers Per Hour"},
2869     {  76, "Feed Per Second"},
2870     {  77, "Feet Per Minute"},
2871     {  78, "Miles Per Hour"},
2872     {  79, "Cubic Feet"},
2873     {  80, "Cubic Meters"},
2874     {  81, "Imperial Gallons"},
2875     {  82, "Liters"},
2876     {  83, "US Gallons"},
2877     {  84, "Cubic Feet Per Minute"},
2878     {  85, "Cubic Meters Per Second"},
2879     {  86, "Imperial Gallons Per Minute"},
2880     {  87, "Liters Per Second"},
2881     {  88, "Liters Per Minute"},
2882     {  89, "US Gallons Per Minute"},
2883     {  90, "Degrees Angular"},
2884     {  91, "Degrees Celsius Per Hour"},
2885     {  92, "Degrees Celsius Per Minute"},
2886     {  93, "Degrees Fahrenheit Per Hour"},
2887     {  94, "Degrees Fahrenheit Per Minute"},
2888     {  95, "No Units"},
2889     {  96, "Parts Per Million"},
2890     {  97, "Parts Per Billion"},
2891     {  98, "Percent"},
2892     {  99, "Pecent Per Second"},
2893     { 100, "Per Minute"},
2894     { 101, "Per Second"},
2895     { 102, "Psi Per Degree Fahrenheit"},
2896     { 103, "Radians"},
2897     { 104, "Revolutions Per Min"},
2898     { 105, "Currency1"},
2899     { 106, "Currency2"},
2900     { 107, "Currency3"},
2901     { 108, "Currency4"},
2902     { 109, "Currency5"},
2903     { 110, "Currency6"},
2904     { 111, "Currency7"},
2905     { 112, "Currency8"},
2906     { 113, "Currency9"},
2907     { 114, "Currency10"},
2908     { 115, "Sq Inches"},
2909     { 116, "Sq Centimeters"},
2910     { 117, "BTUs Per Pound"},
2911     { 118, "Centimeters"},
2912     { 119, "Pounds Mass Per Second"},
2913     { 120, "Delta Degrees Fahrenheit"},
2914     { 121, "Delta Degrees Kelvin"},
2915     { 122, "Kilohms"},
2916     { 123, "Megohms"},
2917     { 124, "Millivolts"},
2918     { 125, "Kilojoules Per Kg"},
2919     { 126, "Megajoules"},
2920     { 127, "Joules Per Degree Kelvin"},
2921     { 128, "Joules Per Kg Degree Kelvin"},
2922     { 129, "Kilohertz"},
2923     { 130, "Megahertz"},
2924     { 131, "Per Hour"},
2925     { 132, "Milliwatts"},
2926     { 133, "Hectopascals"},
2927     { 134, "Millibars"},
2928     { 135, "Cubic Meters Per Hour"},
2929     { 136, "Liters Per Hour"},
2930     { 137, "KWatt Hours Per Square Meter"},
2931     { 138, "KWatt Hours Per Square Foot"},
2932     { 139, "Megajoules Per Square Meter"},
2933     { 140, "Megajoules Per Square Foot"},
2934     { 141, "Watts Per Sq Meter Degree Kelvin"},
2935     { 142, "Cubic Feet Per Second"},
2936     { 143, "Percent Obstruction Per Foot"},
2937     { 144, "Percent Obstruction Per Meter"},
2938     { 145, "milliohms"},
2939     { 146, "megawatt-hours"},
2940     { 147, "kilo-btus"},
2941     { 148, "mega-btus"},
2942     { 149, "kilojoules-per-kilogram-dry-air"},
2943     { 150, "megajoules-per-kilogram-dry-air"},
2944     { 151, "kilojoules-per-degree-Kelvin"},
2945     { 152, "megajoules-per-degree-Kelvin"},
2946     { 153, "newton"},
2947     { 154, "grams-per-second"},
2948     { 155, "grams-per-minute"},
2949     { 156, "tons-per-hour"},
2950     { 157, "kilo-btus-per-hour"},
2951     { 158, "hundredths-seconds"},
2952     { 159, "milliseconds"},
2953     { 160, "newton-meters"},
2954     { 161, "millimeters-per-second"},
2955     { 162, "millimeters-per-minute"},
2956     { 163, "meters-per-minute"},
2957     { 164, "meters-per-hour"},
2958     { 165, "cubic-meters-per-minute"},
2959     { 166, "meters-per-second-per-second"},
2960     { 167, "amperes-per-meter"},
2961     { 168, "amperes-per-square-meter"},
2962     { 169, "ampere-square-meters"},
2963     { 170, "farads"},
2964     { 171, "henrys"},
2965     { 172, "ohm-meters"},
2966     { 173, "siemens"},
2967     { 174, "siemens-per-meter"},
2968     { 175, "teslas"},
2969     { 176, "volts-per-degree-Kelvin"},
2970     { 177, "volts-per-meter"},
2971     { 178, "webers"},
2972     { 179, "candelas"},
2973     { 180, "candelas-per-square-meter"},
2974     { 181, "degrees-Kelvin-per-hour"},
2975     { 182, "degrees-Kelvin-per-minute"},
2976     { 183, "joule-seconds"},
2977     { 184, "radians-per-second"},
2978     { 185, "square-meters-per-Newton"},
2979     { 186, "kilograms-per-cubic-meter"},
2980     { 187, "newton-seconds"},
2981     { 188, "newtons-per-meter"},
2982     { 189, "watts-per-meter-per-degree-Kelvin"},
2983     { 190, "micro-siemens"},
2984     { 191, "cubic-feet-per-hour"},
2985     { 192, "us-gallons-per-hour"},
2986     { 193, "kilometers"},
2987     { 194, "micrometers"},
2988     { 195, "grams"},
2989     { 196, "milligrams"},
2990     { 197, "milliliters"},
2991     { 198, "milliliters-per-second"},
2992     { 199, "decibels"},
2993     { 200, "decibels-millivolt"},
2994     { 201, "decibels-volt"},
2995     { 202, "millisiemens"},
2996     { 203, "watt-hours-reactive"},
2997     { 204, "kilowatt-hours-reactive"},
2998     { 205, "megawatt-hours-reactive"},
2999     { 206, "millimeters-of-water"},
3000     { 207, "per-mille"},
3001     { 208, "grams-per-gram"},
3002     { 209, "kilograms-per-kilogram"},
3003     { 210, "grams-per-kilogram"},
3004     { 211, "milligrams-per-gram"},
3005     { 212, "milligrams-per-kilogram"},
3006     { 213, "grams-per-milliliter"},
3007     { 214, "grams-per-liter"},
3008     { 215, "milligrams-per-liter"},
3009     { 216, "micrograms-per-liter"},
3010     { 217, "grams-per-cubic-meter"},
3011     { 218, "milligrams-per-cubic-meter"},
3012     { 219, "micrograms-per-cubic-meter"},
3013     { 220, "nanograms-per-cubic-meter"},
3014     { 221, "grams-per-cubic-centimeter"},
3015     { 222, "becquerels"},
3016     { 223, "kilobecquerels"},
3017     { 224, "megabecquerels"},
3018     { 225, "gray"},
3019     { 226, "milligray"},
3020     { 227, "microgray"},
3021     { 228, "sieverts"},
3022     { 229, "millisieverts"},
3023     { 230, "microsieverts"},
3024     { 231, "microsieverts-per-hour"},
3025     { 232, "decibels-a"},
3026     { 233, "nephelometric-turbidity-unit"},
3027     { 234, "pH"},
3028     { 235, "grams-per-square-meter"},
3029     { 236, "minutes-per-degree-kelvin"},
3030     { 0,   NULL}
3031 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
3032    Enumerated values 256-65535 may be used by others subject to
3033    the procedures and constraints described in Clause 23. */
3034 };
3035
3036 static const value_string
3037 BACnetErrorCode [] = {
3038     {   0, "other"},
3039     {   1, "authentication-failed"},
3040     {   2, "configuration-in-progress"},
3041     {   3, "device-busy"},
3042     {   4, "dynamic-creation-not-supported"},
3043     {   5, "file-access-denied"},
3044     {   6, "incompatible-security-levels"},
3045     {   7, "inconsistent-parameters"},
3046     {   8, "inconsistent-selection-criterion"},
3047     {   9, "invalid-data-type"},
3048     {  10, "invalid-file-access-method"},
3049     {  11, "invalid-file-start-position"},
3050     {  12, "invalid-operator-name"},
3051     {  13, "invalid-parameter-data-type"},
3052     {  14, "invalid-time-stamp"},
3053     {  15, "key-generation-error"},
3054     {  16, "missing-required-parameter"},
3055     {  17, "no-objects-of-specified-type"},
3056     {  18, "no-space-for-object"},
3057     {  19, "no-space-to-add-list-element"},
3058     {  20, "no-space-to-write-property"},
3059     {  21, "no-vt-sessions-available"},
3060     {  22, "property-is-not-a-list"},
3061     {  23, "object-deletion-not-permitted"},
3062     {  24, "object-identifier-already-exists"},
3063     {  25, "operational-problem"},
3064     {  26, "password-failure"},
3065     {  27, "read-access-denied"},
3066     {  28, "security-not-supported"},
3067     {  29, "service-request-denied"},
3068     {  30, "timeout"},
3069     {  31, "unknown-object"},
3070     {  32, "unknown-property"},
3071     {  33, "removed enumeration"},
3072     {  34, "unknown-vt-class"},
3073     {  35, "unknown-vt-session"},
3074     {  36, "unsupported-object-type"},
3075     {  37, "value-out-of-range"},
3076     {  38, "vt-session-already-closed"},
3077     {  39, "vt-session-termination-failure"},
3078     {  40, "write-access-denied"},
3079     {  41, "character-set-not-supported"},
3080     {  42, "invalid-array-index"},
3081     {  43, "cov-subscription-failed"},
3082     {  44, "not-cov-property"},
3083     {  45, "optional-functionality-not-supported"},
3084     {  46, "invalid-configuration-data"},
3085     {  47, "datatype-not-supported"},
3086     {  48, "duplicate-name"},
3087     {  49, "duplicate-object-id"},
3088     {  50, "property-is-not-an-array"},
3089     {  73, "invalid-event-state"},
3090     {  74, "no-alarm-configured"},
3091     {  75, "log-buffer-full"},
3092     {  76, "logged-value-purged"},
3093     {  77, "no-property-specified"},
3094     {  78, "not-configured-for-triggered-logging"},
3095     {  79, "unknown-subscription"},
3096     {  80, "parameter-out-of-range"},
3097     {  81, "list-element-not-found"},
3098     {  82, "busy"},
3099     {  83, "communication-disabled"},
3100     {  84, "success"},
3101     {  85, "access-denied"},
3102     {  86, "bad-destination-address"},
3103     {  87, "bad-destination-device-id"},
3104     {  88, "bad-signature"},
3105     {  89, "bad-source-address"},
3106     {  90, "bad-timestamp"},
3107     {  91, "cannot-use-key"},
3108     {  92, "cannot-verify-message-id"},
3109     {  93, "correct-key-revision"},
3110     {  94, "destination-device-id-required"},
3111     {  95, "duplicate-message"},
3112     {  96, "encryption-not-configured"},
3113     {  97, "encryption-required"},
3114     {  98, "incorrect-key"},
3115     {  99, "invalid-key-data"},
3116     { 100, "key-update-in-progress"},
3117     { 101, "malformed-message"},
3118     { 102, "not-key-server"},
3119     { 103, "security-not-configured"},
3120     { 104, "source-security-required"},
3121     { 105, "too-many-keys"},
3122     { 106, "unknown-authentication-type"},
3123     { 107, "unknown-key"},
3124     { 108, "unknown-key-revision"},
3125     { 109, "unknown-source-message"},
3126     { 110, "not-router-to-dnet"},
3127     { 111, "router-busy"},
3128     { 112, "unknown-network-message"},
3129     { 113, "message-too-long"},
3130     { 114, "security-error"},
3131     { 115, "addressing-error"},
3132     { 116, "write-bdt-failed"},
3133     { 117, "read-bdt-failed"},
3134     { 118, "register-foreign-device-failed"},
3135     { 119, "read-fdt-failed"},
3136     { 120, "delete-fdt-entry-failed"},
3137     { 121, "distribute-broadcast-failed"},
3138     { 122, "unknown-file-size"},
3139     { 123, "abort-apdu-too-long"},
3140     { 124, "abort-application-exceeded-reply-time"},
3141     { 125, "abort-out-of-resources"},
3142     { 126, "abort-tsm-timeout"},
3143     { 127, "abort-window-size-out-of-range"},
3144     { 128, "file-full"},
3145     { 129, "inconsistent-configuration"},
3146     { 130, "inconsistent-object-type"},
3147     { 131, "internal-error"},
3148     { 132, "not-configured"},
3149     { 133, "out-of-memory"},
3150     { 134, "value-too-long"},
3151     { 135, "abort-insufficient-security"},
3152     { 136, "abort-security-error"},
3153     { 0,   NULL}
3154 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
3155    Enumerated values 256-65535 may be used by others subject to the
3156    procedures and constraints described in Clause 23. */
3157 };
3158
3159 static const value_string
3160 BACnetPropertyIdentifier [] = {
3161     {   0, "acked-transition"},
3162     {   1, "ack-required"},
3163     {   2, "action"},
3164     {   3, "action-text"},
3165     {   4, "active-text"},
3166     {   5, "active-vt-session"},
3167     {   6, "alarm-value"},
3168     {   7, "alarm-values"},
3169     {   8, "all"},
3170     {   9, "all-write-successful"},
3171     {  10, "apdu-segment-timeout"},
3172     {  11, "apdu-timeout"},
3173     {  12, "application-software-version"},
3174     {  13, "archive"},
3175     {  14, "bias"},
3176     {  15, "change-of-state-count"},
3177     {  16, "change-of-state-time"},
3178     {  17, "notification-class"},
3179     {  18, "the property in this place was deleted"},
3180     {  19, "controlled-variable-reference"},
3181     {  20, "controlled-variable-units"},
3182     {  21, "controlled-variable-value"},
3183     {  22, "cov-increment"},
3184     {  23, "datelist"},
3185     {  24, "daylights-savings-status"},
3186     {  25, "deadband"},
3187     {  26, "derivative-constant"},
3188     {  27, "derivative-constant-units"},
3189     {  28, "description"},
3190     {  29, "description-of-halt"},
3191     {  30, "device-address-binding"},
3192     {  31, "device-type"},
3193     {  32, "effective-period"},
3194     {  33, "elapsed-active-time"},
3195     {  34, "error-limit"},
3196     {  35, "event-enable"},
3197     {  36, "event-state"},
3198     {  37, "event-type"},
3199     {  38, "exception-schedule"},
3200     {  39, "fault-values"},
3201     {  40, "feedback-value"},
3202     {  41, "file-access-method"},
3203     {  42, "file-size"},
3204     {  43, "file-type"},
3205     {  44, "firmware-revision"},
3206     {  45, "high-limit"},
3207     {  46, "inactive-text"},
3208     {  47, "in-progress"},
3209     {  48, "instance-of"},
3210     {  49, "integral-constant"},
3211     {  50, "integral-constant-units"},
3212     {  51, "issue-confirmed-notifications"},
3213     {  52, "limit-enable"},
3214     {  53, "list-of-group-members"},
3215     {  54, "list-of-object-property-references"},
3216     {  55, "list-of-session-keys"},
3217     {  56, "local-date"},
3218     {  57, "local-time"},
3219     {  58, "location"},
3220     {  59, "low-limit"},
3221     {  60, "manipulated-variable-reference"},
3222     {  61, "maximum-output"},
3223     {  62, "max-apdu-length-accepted"},
3224     {  63, "max-info-frames"},
3225     {  64, "max-master"},
3226     {  65, "max-pres-value"},
3227     {  66, "minimum-off-time"},
3228     {  67, "minimum-on-time"},
3229     {  68, "minimum-output"},
3230     {  69, "min-pres-value"},
3231     {  70, "model-name"},
3232     {  71, "modification-date"},
3233     {  72, "notify-type"},
3234     {  73, "number-of-APDU-retries"},
3235     {  74, "number-of-states"},
3236     {  75, "object-identifier"},
3237     {  76, "object-list"},
3238     {  77, "object-name"},
3239     {  78, "object-property-reference"},
3240     {  79, "object-type"},
3241     {  80, "optional"},
3242     {  81, "out-of-service"},
3243     {  82, "output-units"},
3244     {  83, "event-parameters"},
3245     {  84, "polarity"},
3246     {  85, "present-value"},
3247     {  86, "priority"},
3248     {  87, "priority-array"},
3249     {  88, "priority-for-writing"},
3250     {  89, "process-identifier"},
3251     {  90, "program-change"},
3252     {  91, "program-location"},
3253     {  92, "program-state"},
3254     {  93, "proportional-constant"},
3255     {  94, "proportional-constant-units"},
3256     {  95, "protocol-conformance-class"},
3257     {  96, "protocol-object-types-supported"},
3258     {  97, "protocol-services-supported"},
3259     {  98, "protocol-version"},
3260     {  99, "read-only"},
3261     { 100, "reason-for-halt"},
3262     { 101, "recipient"},
3263     { 102, "recipient-list"},
3264     { 103, "reliability"},
3265     { 104, "relinquish-default"},
3266     { 105, "required"},
3267     { 106, "resolution"},
3268     { 107, "segmentation-supported"},
3269     { 108, "setpoint"},
3270     { 109, "setpoint-reference"},
3271     { 110, "state-text"},
3272     { 111, "status-flags"},
3273     { 112, "system-status"},
3274     { 113, "time-delay"},
3275     { 114, "time-of-active-time-reset"},
3276     { 115, "time-of-state-count-reset"},
3277     { 116, "time-synchronization-recipients"},
3278     { 117, "units"},
3279     { 118, "update-interval"},
3280     { 119, "utc-offset"},
3281     { 120, "vendor-identifier"},
3282     { 121, "vendor-name"},
3283     { 122, "vt-class-supported"},
3284     { 123, "weekly-schedule"},
3285     { 124, "attempted-samples"},
3286     { 125, "average-value"},
3287     { 126, "buffer-size"},
3288     { 127, "client-cov-increment"},
3289     { 128, "cov-resubscription-interval"},
3290     { 129, "current-notify-time"},
3291     { 130, "event-time-stamp"},
3292     { 131, "log-buffer"},
3293     { 132, "log-device-object-property"},
3294     { 133, "enable"}, /* per ANSI/ASHRAE 135-2004 addendum B */
3295     { 134, "log-interval"},
3296     { 135, "maximum-value"},
3297     { 136, "minimum-value"},
3298     { 137, "notification-threshold"},
3299     { 138, "previous-notify-time"},
3300     { 139, "protocol-revision"},
3301     { 140, "records-since-notification"},
3302     { 141, "record-count"},
3303     { 142, "start-time"},
3304     { 143, "stop-time"},
3305     { 144, "stop-when-full"},
3306     { 145, "total-record-count"},
3307     { 146, "valid-samples"},
3308     { 147, "window-interval"},
3309     { 148, "window-samples"},
3310     { 149, "maximum-value-time-stamp"},
3311     { 150, "minimum-value-time-stamp"},
3312     { 151, "variance-value"},
3313     { 152, "active-cov-subscriptions"},
3314     { 153, "backup-failure-timeout"},
3315     { 154, "configuration-files"},
3316     { 155, "database-revision"},
3317     { 156, "direct-reading"},
3318     { 157, "last-restore-time"},
3319     { 158, "maintenance-required"},
3320     { 159, "member-of"},
3321     { 160, "mode"},
3322     { 161, "operation-expected"},
3323     { 162, "setting"},
3324     { 163, "silenced"},
3325     { 164, "tracking-value"},
3326     { 165, "zone-members"},
3327     { 166, "life-safety-alarm-values"},
3328     { 167, "max-segments-accepted"},
3329     { 168, "profile-name"},
3330     { 169, "auto-slave-discovery"},
3331     { 170, "manual-slave-address-binding"},
3332     { 171, "slave-address-binding"},
3333     { 172, "slave-proxy-enable"},
3334     { 173, "last-notify-record"},     /* bug 4117 */
3335     { 174, "schedule-default"},
3336     { 175, "accepted-modes"},
3337     { 176, "adjust-value"},
3338     { 177, "count"},
3339     { 178, "count-before-change"},
3340     { 179, "count-change-time"},
3341     { 180, "cov-period"},
3342     { 181, "input-reference"},
3343     { 182, "limit-monitoring-interval"},
3344     { 183, "logging-device"},
3345     { 184, "logging-record"},
3346     { 185, "prescale"},
3347     { 186, "pulse-rate"},
3348     { 187, "scale"},
3349     { 188, "scale-factor"},
3350     { 189, "update-time"},
3351     { 190, "value-before-change"},
3352     { 191, "value-set"},
3353     { 192, "value-change-time"},
3354     { 193, "align-intervals"},
3355     { 194, "group-member-names"},
3356     { 195, "interval-offset"},
3357     { 196, "last-restart-reason"},
3358     { 197, "logging-type"},
3359     { 198, "member-status-flags"},
3360     { 199, "notification-period"},
3361     { 200, "previous-notify-record"},
3362     { 201, "requested-update-interval"},
3363     { 202, "restart-notification-recipients"},
3364     { 203, "time-of-device-restart"},
3365     { 204, "time-synchronization-interval"},
3366     { 205, "trigger"},
3367     { 206, "UTC-time-synchronization-recipients"},
3368     { 207, "node-subtype"},
3369     { 208, "node-type"},
3370     { 209, "structured-object-list"},
3371     { 210, "subordinate-annotations"},
3372     { 211, "subordinate-list"},
3373     { 212, "actual-shed-level"},
3374     { 213, "duty-window"},
3375     { 214, "expected-shed-level"},
3376     { 215, "full-duty-baseline"},
3377     { 216, "node-subtype"},
3378     { 217, "node-type"},
3379     { 218, "requested-shed-level"},
3380     { 219, "shed-duration"},
3381     { 220, "shed-level-descriptions"},
3382     { 221, "shed-levels"},
3383     { 222, "state-description"},
3384     /* enumeration values 223-225 are unassigned */
3385     { 226, "door-alarm-state"},
3386     { 227, "door-extended-pulse-time"},
3387     { 228, "door-members"},
3388     { 229, "door-open-too-long-time"},
3389     { 230, "door-pulse-time"},
3390     { 231, "door-status"},
3391     { 232, "door-unlock-delay-time"},
3392     { 233, "lock-status"},
3393     { 234, "masked-alarm-values"},
3394     { 235, "secured-status"},
3395     /* enumeration values 236-243 are unassigned */
3396     { 244, "absentee-limit"},     /* added with addenda 135-2008j */
3397     { 245, "access-alarm-events"},
3398     { 246, "access-doors"},
3399     { 247, "access-event"},
3400     { 248, "access-event-authentication-factor"},
3401     { 249, "access-event-credential"},
3402     { 250, "access-event-time"},
3403     { 251, "access-transaction-events"},
3404     { 252, "accompaniment"},
3405     { 253, "accompaniment-time"},
3406     { 254, "activation-time"},
3407     { 255, "active-authentication-policy"},
3408     { 256, "assigned-access-rights"},
3409     { 257, "authentication-factors"},
3410     { 258, "authentication-policy-list"},
3411     { 259, "authentication-policy-names"},
3412     { 260, "authentication-status"},
3413     { 261, "authorization-mode"},
3414     { 262, "belongs-to"},
3415     { 263, "credential-disable"},
3416     { 264, "credential-status"},
3417     { 265, "credentials"},
3418     { 266, "credentials-in-zone"},
3419     { 267, "days-remaining"},
3420     { 268, "entry-points"},
3421     { 269, "exit-points"},
3422     { 270, "expiry-time"},
3423     { 271, "extended-time-enable"},
3424     { 272, "failed-attempt-events"},
3425     { 273, "failed-attempts"},
3426     { 274, "failed-attempts-time"},
3427     { 275, "last-access-event"},
3428     { 276, "last-access-point"},
3429     { 277, "last-credential-added"},
3430     { 278, "last-credential-added-time"},
3431     { 279, "last-credential-removed"},
3432     { 280, "last-credential-removed-time"},
3433     { 281, "last-use-time"},
3434     { 282, "lockout"},
3435     { 283, "lockout-relinquish-time"},
3436     { 284, "master-exemption"},
3437     { 285, "max-failed-attempts"},
3438     { 286, "members"},
3439     { 287, "muster-point"},
3440     { 288, "negative-access-rules"},
3441     { 289, "number-of-authentication-policies"},
3442     { 290, "occupancy-count"},
3443     { 291, "occupancy-count-adjust"},
3444     { 292, "occupancy-count-enable"},
3445     { 293, "occupancy-exemption"},
3446     { 294, "occupancy-lower-limit"},
3447     { 295, "occupancy-lower-limit-enforced"},
3448     { 296, "occupancy-state"},
3449     { 297, "occupancy-upper-limit"},
3450     { 298, "occupancy-upper-limit-enforced"},
3451     { 299, "passback-exemption"},
3452     { 300, "passback-mode"},
3453     { 301, "passback-timeout"},
3454     { 302, "positive-access-rules"},
3455     { 303, "reason-for-disable"},
3456     { 304, "supported-formats"},
3457     { 305, "supported-format-classes"},
3458     { 306, "threat-authority"},
3459     { 307, "threat-level"},
3460     { 308, "trace-flag"},
3461     { 309, "transaction-notification-class"},
3462     { 310, "user-external-identifier"},
3463     { 311, "user-information-reference"},
3464     /* enumeration values 312-316 are unassigned */
3465     { 317, "user-name"},
3466     { 318, "user-type"},
3467     { 319, "uses-remaining"},
3468     { 320, "zone-from"},
3469     { 321, "zone-to"},
3470     { 322, "access-event-tag"},
3471     { 323, "global-identifier"},
3472     /* enumeration values 324-325 reserved for future addenda */
3473     { 326, "verification-time"},
3474     { 327, "base-device-security-policy"},
3475     { 328, "distribution-key-revision"},
3476     { 329, "do-not-hide"},
3477     { 330, "key-sets"},
3478     { 331, "last-key-server"},
3479     { 332, "network-access-security-policies"},
3480     { 333, "packet-reorder-time"},
3481     { 334, "security-pdu-timeout"},
3482     { 335, "security-time-window"},
3483     { 336, "supported-security-algorithms"},
3484     { 337, "update-key-set-timeout"},
3485     { 338, "backup-and-restore-state"},
3486     { 339, "backup-preparation-time"},
3487     { 340, "restore-completion-time"},
3488     { 341, "restore-preparation-time"},
3489     { 342, "bit-mask"},       /* addenda 135-2008w */
3490     { 343, "bit-text"},
3491     { 344, "is-utc"},
3492     { 345, "group-members"},
3493     { 346, "group-member-names"},
3494     { 347, "member-status-flags"},
3495     { 348, "requested-update-interval"},
3496     { 349, "covu-period"},
3497     { 350, "covu-recipients"},
3498     { 351, "event-message-texts"},
3499     { 0,   NULL}
3500 /* Enumerated values 0-511 are reserved for definition by ASHRAE.
3501    Enumerated values 512-4194303 may be used by others subject to
3502    the procedures and constraints described in Clause 23. */
3503 };
3504
3505 static const value_string
3506 BACnetBinaryPV [] = {
3507     { 0, "inactive"},
3508     { 1, "active"},
3509     { 0, NULL}
3510 };
3511
3512
3513 #define ANSI_X3_4      0 /* ANSI X3.4, a/k/a "ASCII"; full UTF-8 since 2010 */
3514                          /* See, for example, ANSI/ASHRAE Addendum k to ANSI/ASHRAE Standard 135-2008 */
3515                          /* XXX - I've seen captures using this for ISO 8859-1 */
3516 #define IBM_MS_DBCS    1 /* "IBM/Microsoft DBCS"; was there only one such DBCS? */
3517 #define JIS_C_6226     2 /* JIS C 6226 */
3518 #define ISO_10646_UCS4 3 /* ISO 10646 (UCS-4) - 4-byte Unicode */
3519 #define ISO_10646_UCS2 4 /* ISO 10646 (UCS-2) - 2-byte Unicode Basic Multilingual Plane (not UTF-16, presumably) */
3520 #define ISO_8859_1     5 /* ISO 8859-1 */
3521 static const value_string
3522 BACnetCharacterSet [] = {
3523     { ANSI_X3_4,      "ANSI X3.4 / UTF-8 (since 2010)"},
3524     { IBM_MS_DBCS,    "IBM/Microsoft DBCS"},
3525     { JIS_C_6226,     "JIS C 6226"},
3526     { ISO_10646_UCS4, "ISO 10646 (UCS-4)"},
3527     { ISO_10646_UCS2, "ISO 10646 (UCS-2)"},
3528     { ISO_8859_1,     "ISO 8859-1"},
3529     { 0,     NULL}
3530 };
3531
3532 static const value_string
3533 BACnetStatusFlags [] = {
3534     { 0, "in-alarm"},
3535     { 1, "fault"},
3536     { 2, "overridden"},
3537     { 3, "out-of-service"},
3538     { 0, NULL}
3539 };
3540
3541 static const value_string
3542 BACnetMessagePriority [] = {
3543     { 0, "normal"},
3544     { 1, "urgent"},
3545     { 0, NULL}
3546 };
3547
3548 static const value_string
3549 BACnetAcknowledgementFilter [] = {
3550     { 0, "all"},
3551     { 1, "acked"},
3552     { 2, "not-acked"},
3553     { 0, NULL}
3554 };
3555
3556 static const value_string
3557 BACnetResultFlags [] = {
3558     { 0, "firstitem"},
3559     { 1, "lastitem"},
3560     { 2, "moreitems"},
3561     { 0, NULL}
3562 };
3563
3564 static const value_string
3565 BACnetRelationSpecifier [] = {
3566     { 0, "equal"},
3567     { 1, "not-equal"},
3568     { 2, "less-than"},
3569     { 3, "greater-than"},
3570     { 4, "less-than-or-equal"},
3571     { 5, "greater-than-or-equal"},
3572     { 0, NULL}
3573 };
3574
3575 static const value_string
3576 BACnetSelectionLogic [] = {
3577     { 0, "and"},
3578     { 1, "or"},
3579     { 2, "all"},
3580     { 0, NULL}
3581 };
3582
3583 static const value_string
3584 BACnetEventStateFilter [] = {
3585     { 0, "offnormal"},
3586     { 1, "fault"},
3587     { 2, "normal"},
3588     { 3, "all"},
3589     { 4, "active"},
3590     { 0, NULL}
3591 };
3592
3593 static const value_string
3594 BACnetEventTransitionBits [] = {
3595     { 0, "to-offnormal"},
3596     { 1, "to-fault"},
3597     { 2, "to-normal"},
3598     { 0, NULL}
3599 };
3600
3601 static const value_string
3602 BACnetSegmentation [] = {
3603     { 0, "segmented-both"},
3604     { 1, "segmented-transmit"},
3605     { 2, "segmented-receive"},
3606     { 3, "no-segmentation"},
3607     { 0, NULL}
3608 };
3609
3610 static const value_string
3611 BACnetSilencedState [] = {
3612     { 0, "unsilenced"},
3613     { 1, "audible-silenced"},
3614     { 2, "visible-silenced"},
3615     { 3, "all-silenced"},
3616     { 0, NULL}
3617 };
3618
3619 static const value_string
3620 BACnetDeviceStatus [] = {
3621     { 0, "operational"},
3622     { 1, "operational-read-only"},
3623     { 2, "download-required"},
3624     { 3, "download-in-progress"},
3625     { 4, "non-operational"},
3626     { 5, "backup-in-progress"},
3627     { 0, NULL}
3628 };
3629
3630 static const value_string
3631 BACnetEnableDisable [] = {
3632     { 0, "enable"},
3633     { 1, "disable"},
3634     { 2, "disable-initiation"},
3635     { 0, NULL}
3636 };
3637
3638 static const value_string
3639 months [] = {
3640     {   1, "January" },
3641     {   2, "February" },
3642     {   3, "March" },
3643     {   4, "April" },
3644     {   5, "May" },
3645     {   6, "June" },
3646     {   7, "July" },
3647     {   8, "August" },
3648     {   9, "September" },
3649     {  10, "October" },
3650     {  11, "November" },
3651     {  12, "December" },
3652     { 255, "any month" },
3653     { 0,   NULL }
3654 };
3655
3656 static const value_string
3657 weekofmonth [] = {
3658     {   1, "days numbered 1-7" },
3659     {   2, "days numbered 8-14" },
3660     {   3, "days numbered 15-21" },
3661     {   4, "days numbered 22-28" },
3662     {   5, "days numbered 29-31" },
3663     {   6, "last 7 days of this month" },
3664     { 255, "any week of this month" },
3665     { 0,   NULL }
3666 };
3667
3668 /* note: notification class object recipient-list uses
3669    different day-of-week enum */
3670 static const value_string
3671 day_of_week [] = {
3672     {   1, "Monday" },
3673     {   2, "Tuesday" },
3674     {   3, "Wednesday" },
3675     {   4, "Thursday" },
3676     {   5, "Friday" },
3677     {   6, "Saturday" },
3678     {   7, "Sunday" },
3679     { 255, "any day of week" },
3680     { 0,   NULL }
3681 };
3682
3683 static const value_string
3684 BACnetErrorClass [] = {
3685     { 0, "device" },
3686     { 1, "object" },
3687     { 2, "property" },
3688     { 3, "resources" },
3689     { 4, "security" },
3690     { 5, "services" },
3691     { 6, "vt" },
3692     { 7, "communication" },
3693     { 0, NULL }
3694 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3695    Enumerated values64-65535 may be used by others subject to
3696    the procedures and constraints described in Clause 23. */
3697 };
3698
3699 static const value_string
3700 BACnetVTClass [] = {
3701     { 0, "default-terminal" },
3702     { 1, "ansi-x3-64" },
3703     { 2, "dec-vt52" },
3704     { 3, "dec-vt100" },
3705     { 4, "dec-vt200" },
3706     { 5, "hp-700-94" },
3707     { 6, "ibm-3130" },
3708     { 0, NULL }
3709 };
3710
3711 static const value_string
3712 BACnetEventType [] = {
3713     {  0, "change-of-bitstring" },
3714     {  1, "change-of-state" },
3715     {  2, "change-of-value" },
3716     {  3, "command-failure" },
3717     {  4, "floating-limit" },
3718     {  5, "out-of-range" },
3719     {  6, "complex-event-type" },
3720     {  7, "(deprecated)buffer-ready" },
3721     {  8, "change-of-life-safety" },
3722     {  9, "extended" },
3723     { 10, "buffer-ready" },
3724     { 11, "unsigned-range" },
3725     { 14, "double-out-of-range"},     /* added with addenda 135-2008w */
3726     { 15, "signed-out-of-range"},
3727     { 16, "unsigned-out-of-range"},
3728     { 17, "change-of-characterstring"},
3729     { 18, "change-of-status-flags"},
3730     { 0,  NULL }
3731 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3732    Enumerated values 64-65535 may be used by others subject to
3733    the procedures and constraints described in Clause 23.
3734    It is expected that these enumerated values will correspond
3735    to the use of the complex-event-type CHOICE [6] of the
3736    BACnetNotificationParameters production. */
3737 };
3738
3739 static const value_string
3740 BACnetEventState [] = {
3741     { 0, "normal" },
3742     { 1, "fault" },
3743     { 2, "offnormal" },
3744     { 3, "high-limit" },
3745     { 4, "low-limit" },
3746     { 5, "life-safety-alarm" },
3747     { 0, NULL }
3748 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3749    Enumerated values 64-65535 may be used by others subject to
3750    the procedures and constraints described in Clause 23.  */
3751 };
3752
3753 static const value_string
3754 BACnetLogStatus [] = {
3755     { 0, "log-disabled" },
3756     { 1, "buffer-purged" },
3757     { 2, "log-interrupted"},
3758     { 0, NULL }
3759 };
3760
3761 static const value_string
3762 BACnetMaintenance [] = {
3763     { 0, "none" },
3764     { 1, "periodic-test" },
3765     { 2, "need-service-operational" },
3766     { 3, "need-service-inoperative" },
3767     { 0, NULL }
3768 };
3769
3770 static const value_string
3771 BACnetNotifyType [] = {
3772     { 0, "alarm" },
3773     { 1, "event" },
3774     { 2, "ack-notification" },
3775     { 0, NULL }
3776 };
3777
3778 static const value_string
3779 BACnetServicesSupported [] = {
3780     {  0, "acknowledgeAlarm"},
3781     {  1, "confirmedCOVNotification"},
3782     {  2, "confirmedEventNotification"},
3783     {  3, "getAlarmSummary"},
3784     {  4, "getEnrollmentSummary"},
3785     {  5, "subscribeCOV"},
3786     {  6, "atomicReadFile"},
3787     {  7, "atomicWriteFile"},
3788     {  8, "addListElement"},
3789     {  9, "removeListElement"},
3790     { 10, "createObject"},
3791     { 11, "deleteObject"},
3792     { 12, "readProperty"},
3793     { 13, "readPropertyConditional"},
3794     { 14, "readPropertyMultiple"},
3795     { 15, "writeProperty"},
3796     { 16, "writePropertyMultiple"},
3797     { 17, "deviceCommunicationControl"},
3798     { 18, "confirmedPrivateTransfer"},
3799     { 19, "confirmedTextMessage"},
3800     { 20, "reinitializeDevice"},
3801     { 21, "vtOpen"},
3802     { 22, "vtClose"},
3803     { 23, "vtData"},
3804     { 24, "authenticate"},
3805     { 25, "requestKey"},
3806     { 26, "i-Am"},
3807     { 27, "i-Have"},
3808     { 28, "unconfirmedCOVNotification"},
3809     { 29, "unconfirmedEventNotification"},
3810     { 30, "unconfirmedPrivateTransfer"},
3811     { 31, "unconfirmedTextMessage"},
3812     { 32, "timeSynchronization"},
3813     { 33, "who-Has"},
3814     { 34, "who-Is"},
3815     { 35, "readRange"},
3816     { 36, "utcTimeSynchronization"},
3817     { 37, "lifeSafetyOperation"},
3818     { 38, "subscribeCOVProperty"},
3819     { 39, "getEventInformation"},
3820     { 0,  NULL}
3821 };
3822
3823 static const value_string
3824 BACnetPropertyStates [] = {
3825     {  0, "boolean-value"},
3826     {  1, "binary-value"},
3827     {  2, "event-type"},
3828     {  3, "polarity"},
3829     {  4, "program-change"},
3830     {  5, "program-state"},
3831     {  6, "reason-for-halt"},
3832     {  7, "reliability"},
3833     {  8, "state"},
3834     {  9, "system-status"},
3835     { 10, "units"},
3836     { 11, "unsigned-value"},
3837     { 12, "life-safety-mode"},
3838     { 13, "life-safety-state"},
3839     { 14, "restart-reason"},
3840     { 15, "door-alarm-state"},
3841     { 16, "action"},
3842     { 17, "door-secured-status"},
3843     { 18, "door-status"},
3844     { 19, "door-value"},
3845     { 20, "file-access-method"},
3846     { 21, "lock-status"},
3847     { 22, "life-safety-operation"},
3848     { 23, "maintenance"},
3849     { 24, "node-type"},
3850     { 25, "notify-type"},
3851     { 26, "security-level"},
3852     { 27, "shed-state"},
3853     { 28, "silenced-state"},
3854     /* context tag 29 reserved for future addenda */
3855     { 29, "unknown-29"},
3856     { 30, "access-event"},
3857     { 31, "zone-occupancy-state"},
3858     { 32, "access-credential-disable-reason"},
3859     { 33, "access-credential-disable"},
3860     { 34, "authentication-status"},
3861     { 35, "unknown-35"},
3862     { 36, "backup-state"},
3863     { 0, NULL}
3864 /* Tag values 0-63 are reserved for definition by ASHRAE.
3865    Tag values of 64-254 may be used by others to accommodate
3866    vendor specific properties that have discrete or enumerated values,
3867    subject to the constraints described in Clause 23. */
3868 };
3869
3870 static const value_string
3871 BACnetProgramError [] = {
3872     { 0, "normal"},
3873     { 1, "load-failed"},
3874     { 2, "internal"},
3875     { 3, "program"},
3876     { 4, "other"},
3877     { 0, NULL}
3878 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3879    Enumerated values 64-65535 may be used by others subject to
3880    the procedures and constraints described in Clause 23. */
3881 };
3882
3883 static const value_string
3884 BACnetProgramRequest [] = {
3885     { 0, "ready"},
3886     { 1, "load"},
3887     { 2, "run"},
3888     { 3, "halt"},
3889     { 4, "restart"},
3890     { 4, "unload"},
3891     { 0, NULL}
3892 };
3893
3894 static const value_string
3895 BACnetProgramState [] = {
3896     { 0, "idle"},
3897     { 1, "loading"},
3898     { 2, "running"},
3899     { 3, "waiting"},
3900     { 4, "halted"},
3901     { 4, "unloading"},
3902     { 0, NULL}
3903 };
3904
3905 static const value_string
3906 BACnetReinitializedStateOfDevice [] = {
3907     { 0, "coldstart"},
3908     { 1, "warmstart"},
3909     { 2, "startbackup"},
3910     { 3, "endbackup"},
3911     { 4, "startrestore"},
3912     { 5, "endrestore"},
3913     { 6, "abortrestore"},
3914     { 0, NULL}
3915 };
3916
3917 static const value_string
3918 BACnetPolarity [] = {
3919     { 0, "normal"},
3920     { 1, "reverse"},
3921     { 0, NULL}
3922 };
3923
3924 static const value_string
3925 BACnetTagNames[] = {
3926     { 5, "Extended Value" },
3927     { 6, "Opening Tag" },
3928     { 7, "Closing Tag" },
3929     { 0, NULL }
3930 };
3931
3932 static const value_string
3933 BACnetReadRangeOptions[] = {
3934     { 3, "range byPosition" },
3935     { 4, "range byTime" },
3936     { 5, "range timeRange" },
3937     { 6, "range bySequenceNumber" },
3938     { 7, "range byTime" },
3939     { 0, NULL }
3940 };
3941
3942 /* Present_Value for Load Control Object */
3943 static const value_string
3944 BACnetShedState[] = {
3945     { 0, "shed-inactive" },
3946     { 1, "shed-request-pending" },
3947     { 2, "shed-compliant" },
3948     { 3, "shed-non-compliant" },
3949     { 0, NULL }
3950 };
3951
3952 static const value_string
3953 BACnetNodeType [] = {
3954     { 0, "unknown" },
3955     { 1, "system" },
3956     { 2, "network" },
3957     { 3, "device" },
3958     { 4, "organizational" },
3959     { 5, "area" },
3960     { 6, "equipment" },
3961     { 7, "point" },
3962     { 8, "collection" },
3963     { 9, "property" },
3964     { 10, "functional" },
3965     { 11, "other" },
3966     { 0, NULL }
3967 };
3968
3969 static const value_string
3970 BACnetLoggingType [] = {
3971     { 0, "polled" },
3972     { 1, "cov" },
3973     { 2, "triggered" },
3974     { 0, NULL }
3975 };
3976
3977 static const value_string
3978 BACnetDoorStatus [] = {
3979     { 0, "closed" },
3980     { 1, "opened" },
3981     { 2, "unknown" },
3982     { 0, NULL }
3983 };
3984
3985 static const value_string
3986 BACnetLockStatus [] = {
3987     { 0, "locked" },
3988     { 1, "unlocked" },
3989     { 2, "fault" },
3990     { 3, "unknown" },
3991     { 0, NULL }
3992 };
3993
3994 static const value_string
3995 BACnetDoorSecuredStatus [] = {
3996     { 0, "secured" },
3997     { 1, "unsecured" },
3998     { 2, "unknown" },
3999     { 0, NULL }
4000 };
4001
4002 static const value_string
4003 BACnetDoorAlarmState [] = {
4004     { 0, "normal" },
4005     { 1, "alarm" },
4006     { 2, "door-open-too-long" },
4007     { 3, "forced-open" },
4008     { 4, "tamper" },
4009     { 5, "door-fault" },
4010     { 6, "lock-down" },
4011     { 7, "free-access" },
4012     { 8, "egress-open" },
4013     { 0, NULL }
4014 };
4015
4016 static const value_string
4017 BACnetAccumulatorStatus [] = {
4018     { 0, "normal" },
4019     { 1, "starting" },
4020     { 2, "recovered" },
4021     { 3, "abnormal" },
4022     { 4, "failed" },
4023     { 0, NULL }
4024 };
4025
4026 /* These values are (manually) transferred from
4027  * http://www.bacnet.org/VendorID/BACnet Vendor IDs.htm
4028  * Version: "As of September 16, 2013"
4029  */
4030
4031 static const value_string
4032 BACnetVendorIdentifiers [] = {
4033     {   0, "ASHRAE" },
4034     {   1, "NIST" },
4035     {   2, "The Trane Company" },
4036     {   3, "McQuay International" },
4037     {   4, "PolarSoft" },
4038     {   5, "Johnson Controls, Inc." },
4039     {   6, "American Auto-Matrix" },
4040     {   7, "Siemens Schweiz AG (Formerly: Landis & Staefa Division Europe)" },
4041     {   8, "Delta Controls" },
4042     {   9, "Siemens Schweiz AG" },
4043     {  10, "Schneider Electric" },
4044     {  11, "TAC" },
4045     {  12, "Orion Analysis Corporation" },
4046     {  13, "Teletrol Systems Inc." },
4047     {  14, "Cimetrics Technology" },
4048     {  15, "Cornell University" },
4049     {  16, "United Technologies Carrier" },
4050     {  17, "Honeywell Inc." },
4051     {  18, "Alerton / Honeywell" },
4052     {  19, "TAC AB" },
4053     {  20, "Hewlett-Packard Company" },
4054     {  21, "Dorsette's Inc." },
4055     {  22, "Siemens Schweiz AG (Formerly: Cerberus AG)" },
4056     {  23, "York Controls Group" },
4057     {  24, "Automated Logic Corporation" },
4058     {  25, "CSI Control Systems International" },
4059     {  26, "Phoenix Controls Corporation" },
4060     {  27, "Innovex Technologies, Inc." },
4061     {  28, "KMC Controls, Inc." },
4062     {  29, "Xn Technologies, Inc." },
4063     {  30, "Hyundai Information Technology Co., Ltd." },
4064     {  31, "Tokimec Inc." },
4065     {  32, "Simplex" },
4066     {  33, "North Building Technologies Limited" },
4067     {  34, "Notifier" },
4068     {  35, "Reliable Controls Corporation" },
4069     {  36, "Tridium Inc." },
4070     {  37, "Sierra Monitor Corporation/FieldServer Technologies" },
4071     {  38, "Silicon Energy" },
4072     {  39, "Kieback & Peter GmbH & Co KG" },
4073     {  40, "Anacon Systems, Inc." },
4074     {  41, "Systems Controls & Instruments, LLC" },
4075     {  42, "Lithonia Lighting" },
4076     {  43, "Micropower Manufacturing" },
4077     {  44, "Matrix Controls" },
4078     {  45, "METALAIRE" },
4079     {  46, "ESS Engineering" },
4080     {  47, "Sphere Systems Pty Ltd." },
4081     {  48, "Walker Technologies Corporation" },
4082     {  49, "H I Solutions, Inc." },
4083     {  50, "MBS GmbH" },
4084     {  51, "SAMSON AG" },
4085     {  52, "Badger Meter Inc." },
4086     {  53, "DAIKIN Industries Ltd." },
4087     {  54, "NARA Controls Inc." },
4088     {  55, "Mammoth Inc." },
4089     {  56, "Liebert Corporation" },
4090     {  57, "SEMCO Incorporated" },
4091     {  58, "Air Monitor Corporation" },
4092     {  59, "TRIATEK, LLC" },
4093     {  60, "NexLight" },
4094     {  61, "Multistack" },
4095     {  62, "TSI Incorporated" },
4096     {  63, "Weather-Rite, Inc." },
4097     {  64, "Dunham-Bush" },
4098     {  65, "Reliance Electric" },
4099     {  66, "LCS Inc." },
4100     {  67, "Regulator Australia PTY Ltd." },
4101     {  68, "Touch-Plate Lighting Controls" },
4102     {  69, "Amann GmbH" },
4103     {  70, "RLE Technologies" },
4104     {  71, "Cardkey Systems" },
4105     {  72, "SECOM Co., Ltd." },
4106     {  73, "ABB Gebaudetechnik AG Bereich NetServ" },
4107     {  74, "KNX Association cvba" },
4108     {  75, "Institute of Electrical Installation Engineers of Japan (IEIEJ)" },
4109     {  76, "Nohmi Bosai, Ltd." },
4110     {  77, "Carel S.p.A." },
4111     {  78, "AirSense Technology, Inc." },
4112     {  79, "Hochiki Corporation" },
4113     {  80, "Fr. Sauter AG" },
4114     {  81, "Matsushita Electric Works, Ltd." },
4115     {  82, "Mitsubishi Electric Corporation, Inazawa Works" },
4116     {  83, "Mitsubishi Heavy Industries, Ltd." },
4117     {  84, "ITT Bell & Gossett" },
4118     {  85, "Yamatake Building Systems Co., Ltd." },
4119     {  86, "The Watt Stopper, Inc." },
4120     {  87, "Aichi Tokei Denki Co., Ltd." },
4121     {  88, "Activation Technologies, LLC" },
4122     {  89, "Saia-Burgess Controls, Ltd." },
4123     {  90, "Hitachi, Ltd." },
4124     {  91, "Novar Corp./Trend Control Systems Ltd." },
4125     {  92, "Mitsubishi Electric Lighting Corporation" },
4126     {  93, "Argus Control Systems, Ltd." },
4127     {  94, "Kyuki Corporation" },
4128     {  95, "Richards-Zeta Building Intelligence, Inc." },
4129     {  96, "Scientech R&D, Inc." },
4130     {  97, "VCI Controls, Inc." },
4131     {  98, "Toshiba Corporation" },
4132     {  99, "Mitsubishi Electric Corporation Air Conditioning & Refrigeration Systems Works" },
4133     { 100, "Custom Mechanical Equipment, LLC" },
4134     { 101, "ClimateMaster" },
4135     { 102, "ICP Panel-Tec, Inc." },
4136     { 103, "D-Tek Controls" },
4137     { 104, "NEC Engineering, Ltd." },
4138     { 105, "PRIVA BV" },
4139     { 106, "Meidensha Corporation" },
4140     { 107, "JCI Systems Integration Services" },
4141     { 108, "Freedom Corporation" },
4142     { 109, "Neuberger Gebaudeautomation GmbH" },
4143     { 110, "Sitronix" },
4144     { 111, "Leviton Manufacturing" },
4145     { 112, "Fujitsu Limited" },
4146     { 113, "Emerson Network Power" },
4147     { 114, "S. A. Armstrong, Ltd." },
4148     { 115, "Visonet AG" },
4149     { 116, "M&M Systems, Inc." },
4150     { 117, "Custom Software Engineering" },
4151     { 118, "Nittan Company, Limited" },
4152     { 119, "Elutions Inc. (Wizcon Systems SAS)" },
4153     { 120, "Pacom Systems Pty., Ltd." },
4154     { 121, "Unico, Inc." },
4155     { 122, "Ebtron, Inc." },
4156     { 123, "Scada Engine" },
4157     { 124, "AC Technology Corporation" },
4158     { 125, "Eagle Technology" },
4159     { 126, "Data Aire, Inc." },
4160     { 127, "ABB, Inc." },
4161     { 128, "Transbit Sp. z o. o." },
4162     { 129, "Toshiba Carrier Corporation" },
4163     { 130, "Shenzhen Junzhi Hi-Tech Co., Ltd." },
4164     { 131, "Tokai Soft" },
4165     { 132, "Blue Ridge Technologies" },
4166     { 133, "Veris Industries" },
4167     { 134, "Centaurus Prime" },
4168     { 135, "Sand Network Systems" },
4169     { 136, "Regulvar, Inc." },
4170     { 137, "AFDtek Division of Fastek International Inc." },
4171     { 138, "PowerCold Comfort Air Solutions, Inc." },
4172     { 139, "I Controls" },
4173     { 140, "Viconics Electronics, Inc." },
4174     { 141, "Yaskawa America, Inc." },
4175     { 142, "DEOS control systems GmbH" },
4176     { 143, "Digitale Mess- und Steuersysteme AG" },
4177     { 144, "Fujitsu General Limited" },
4178     { 145, "Project Engineering S.r.l." },
4179     { 146, "Sanyo Electric Co., Ltd." },
4180     { 147, "Integrated Information Systems, Inc." },
4181     { 148, "Temco Controls, Ltd." },
4182     { 149, "Airtek International Inc." },
4183     { 150, "Advantech Corporation" },
4184     { 151, "Titan Products, Ltd." },
4185     { 152, "Regel Partners" },
4186     { 153, "National Environmental Product" },
4187     { 154, "Unitec Corporation" },
4188     { 155, "Kanden Engineering Company" },
4189     { 156, "Messner Gebaudetechnik GmbH" },
4190     { 157, "Integrated.CH" },
4191     { 158, "Price Industries" },
4192     { 159, "SE-Elektronic GmbH" },
4193     { 160, "Rockwell Automation" },
4194     { 161, "Enflex Corp." },
4195     { 162, "ASI Controls" },
4196     { 163, "SysMik GmbH Dresden" },
4197     { 164, "HSC Regelungstechnik GmbH" },
4198     { 165, "Smart Temp Australia Pty. Ltd." },
4199     { 166, "Cooper Controls" },
4200     { 167, "Duksan Mecasys Co., Ltd." },
4201     { 168, "Fuji IT Co., Ltd." },
4202     { 169, "Vacon Plc" },
4203     { 170, "Leader Controls" },
4204     { 171, "Cylon Controls, Ltd." },
4205     { 172, "Compas" },
4206     { 173, "Mitsubishi Electric Building Techno-Service Co., Ltd." },
4207     { 174, "Building Control Integrators" },
4208     { 175, "ITG Worldwide (M) Sdn Bhd" },
4209     { 176, "Lutron Electronics Co., Inc." },
4210     { 178, "LOYTEC Electronics GmbH" },
4211     { 179, "ProLon" },
4212     { 180, "Mega Controls Limited" },
4213     { 181, "Micro Control Systems, Inc." },
4214     { 182, "Kiyon, Inc." },
4215     { 183, "Dust Networks" },
4216     { 184, "Advanced Building Automation Systems" },
4217     { 185, "Hermos AG" },
4218     { 186, "CEZIM" },
4219     { 187, "Softing" },
4220     { 188, "Lynxspring" },
4221     { 189, "Schneider Toshiba Inverter Europe" },
4222     { 190, "Danfoss Drives A/S" },
4223     { 191, "Eaton Corporation" },
4224     { 192, "Matyca S.A." },
4225     { 193, "Botech AB" },
4226     { 194, "Noveo, Inc." },
4227     { 195, "AMEV" },
4228     { 196, "Yokogawa Electric Corporation" },
4229     { 197, "GFR Gesellschaft fur Regelungstechnik" },
4230     { 198, "Exact Logic" },
4231     { 199, "Mass Electronics Pty Ltd dba Innotech Control Systems Australia" },
4232     { 200, "Kandenko Co., Ltd." },
4233     { 201, "DTF, Daten-Technik Fries" },
4234     { 202, "Klimasoft, Ltd." },
4235     { 203, "Toshiba Schneider Inverter Corporation" },
4236     { 204, "Control Applications, Ltd." },
4237     { 205, "KDT Systems Co., Ltd." },
4238     { 206, "Onicon Incorporated" },
4239     { 207, "Automation Displays, Inc." },
4240     { 208, "Control Solutions, Inc." },
4241     { 209, "Remsdaq Limited" },
4242     { 210, "NTT Facilities, Inc." },
4243     { 211, "VIPA GmbH" },
4244     { 212, "TSC21 Association of Japan" },
4245     { 213, "Strato Automation" },
4246     { 214, "HRW Limited" },
4247     { 215, "Lighting Control & Design, Inc." },
4248     { 216, "Mercy Electronic and Electrical Industries" },
4249     { 217, "Samsung SDS Co., Ltd" },
4250     { 218, "Impact Facility Solutions, Inc." },
4251     { 219, "Aircuity" },
4252     { 220, "Control Techniques, Ltd." },
4253     { 221, "OpenGeneral Pty., Ltd." },
4254     { 222, "WAGO Kontakttechnik GmbH & Co. KG" },
4255     { 223, "Cerus Industrial" },
4256     { 224, "Chloride Power Protection Company" },
4257     { 225, "Computrols, Inc." },
4258     { 226, "Phoenix Contact GmbH & Co. KG" },
4259     { 227, "Grundfos Management A/S" },
4260     { 228, "Ridder Drive Systems" },
4261     { 229, "Soft Device SDN BHD" },
4262     { 230, "Integrated Control Technology Limited" },
4263     { 231, "AIRxpert Systems, Inc." },
4264     { 232, "Microtrol Limited" },
4265     { 233, "Red Lion Controls" },
4266     { 234, "Digital Electronics Corporation" },
4267     { 235, "Ennovatis GmbH" },
4268     { 236, "Serotonin Software Technologies, Inc." },
4269     { 237, "LS Industrial Systems Co., Ltd." },
4270     { 238, "Square D Company" },
4271     { 239, "S Squared Innovations, Inc." },
4272     { 240, "Aricent Ltd." },
4273     { 241, "EtherMetrics, LLC" },
4274     { 242, "Industrial Control Communications, Inc." },
4275     { 243, "Paragon Controls, Inc." },
4276     { 244, "A. O. Smith Corporation" },
4277     { 245, "Contemporary Control Systems, Inc." },
4278     { 246, "Intesis Software SL" },
4279     { 247, "Ingenieurgesellschaft N. Hartleb mbH" },
4280     { 248, "Heat-Timer Corporation" },
4281     { 249, "Ingrasys Technology, Inc." },
4282     { 250, "Costerm Building Automation" },
4283     { 251, "WILO SE" },
4284     { 252, "Embedia Technologies Corp." },
4285     { 253, "Technilog" },
4286     { 254, "HR Controls Ltd. & Co. KG" },
4287     { 255, "Lennox International, Inc." },
4288     { 256, "RK-Tec Rauchklappen-Steuerungssysteme GmbH & Co. KG" },
4289     { 257, "Thermomax, Ltd." },
4290     { 258, "ELCON Electronic Control, Ltd." },
4291     { 259, "Larmia Control AB" },
4292     { 260, "BACnet Stack at SourceForge" },
4293     { 261, "G4S Security Services A/S" },
4294     { 262, "Exor International S.p.A." },
4295     { 263, "Cristal Controles" },
4296     { 264, "Regin AB" },
4297     { 265, "Dimension Software, Inc." },
4298     { 266, "SynapSense Corporation" },
4299     { 267, "Beijing Nantree Electronic Co., Ltd." },
4300     { 268, "Camus Hydronics Ltd." },
4301     { 269, "Kawasaki Heavy Industries, Ltd." },
4302     { 270, "Critical Environment Technologies" },
4303     { 271, "ILSHIN IBS Co., Ltd." },
4304     { 272, "ELESTA Energy Control AG" },
4305     { 273, "KROPMAN Installatietechniek" },
4306     { 274, "Baldor Electric Company" },
4307     { 275, "INGA mbH" },
4308     { 276, "GE Consumer & Industrial" },
4309     { 277, "Functional Devices, Inc." },
4310     { 278, "ESAC" },
4311     { 279, "M-System Co., Ltd." },
4312     { 280, "Yokota Co., Ltd." },
4313     { 281, "Hitranse Technology Co., LTD" },
4314     { 282, "Federspiel Controls" },
4315     { 283, "Kele, Inc." },
4316     { 284, "Opera Electronics, Inc." },
4317     { 285, "Gentec" },
4318     { 286, "Embedded Science Labs, LLC" },
4319     { 287, "Parker Hannifin Corporation" },
4320     { 288, "MaCaPS International Limited" },
4321     { 289, "Link4 Corporation" },
4322     { 290, "Romutec Steuer-u. Regelsysteme GmbH" },
4323     { 291, "Pribusin, Inc." },
4324     { 292, "Advantage Controls" },
4325     { 293, "Critical Room Control" },
4326     { 294, "LEGRAND" },
4327     { 295, "Tongdy Control Technology Co., Ltd." },
4328     { 296, "ISSARO Integrierte Systemtechnik" },
4329     { 297, "Pro-Dev Industries" },
4330     { 298, "DRI-STEEM" },
4331     { 299, "Creative Electronic GmbH" },
4332     { 300, "Swegon AB" },
4333     { 301, "Jan Brachacek" },
4334     { 302, "Hitachi Appliances, Inc." },
4335     { 303, "Real Time Automation, Inc." },
4336     { 304, "ITEC Hankyu-Hanshin Co." },
4337     { 305, "Cyrus E&M Engineering Co., Ltd." },
4338     { 306, "Racine Federated, Inc." },
4339     { 307, "Cirrascale Corporation" },
4340     { 308, "Elesta GmbH Building Automation" },
4341     { 309, "Securiton" },
4342     { 310, "OSlsoft, Inc." },
4343     { 311, "Hanazeder Electronic GmbH" },
4344     { 312, "Honeywell Security Deutschland, Novar GmbH" },
4345     { 313, "Siemens Energy & Automation, Inc." },
4346     { 314, "ETM Professional Control GmbH" },
4347     { 315, "Meitav-tec, Ltd." },
4348     { 316, "Janitza Electronics GmbH" },
4349     { 317, "MKS Nordhausen" },
4350     { 318, "De Gier Drive Systems B.V." },
4351     { 319, "Cypress Envirosystems" },
4352     { 320, "SMARTron s.r.o." },
4353     { 321, "Verari Systems, Inc." },
4354     { 322, "K-W Electronic Service, Inc." },
4355     { 323, "ALFA-SMART Energy Management" },
4356     { 324, "Telkonet, Inc." },
4357     { 325, "Securiton GmbH" },
4358     { 326, "Cemtrex, Inc." },
4359     { 327, "Performance Technologies, Inc." },
4360     { 328, "Xtralis (Aust) Pty Ltd" },
4361     { 329, "TROX GmbH" },
4362     { 330, "Beijing Hysine Technology Co., Ltd" },
4363     { 331, "RCK Controls, Inc." },
4364     { 332, "Distech Controls SAS" },
4365     { 333, "Novar/Honeywell" },
4366     { 334, "The S4 Group, Inc." },
4367     { 335, "Schneider Electric" },
4368     { 336, "LHA Systems" },
4369     { 337, "GHM engineering Group, Inc." },
4370     { 338, "Cllimalux S.A." },
4371     { 339, "VAISALA Oyj" },
4372     { 340, "COMPLEX (Beijing) Technology, Co., LTD." },
4373     { 341, "SCADAmetrics" },
4374     { 342, "POWERPEG NSI Limited" },
4375     { 343, "BACnet Interoperability Testing Services, Inc." },
4376     { 344, "Teco a.s." },
4377     { 345, "Plexus Technology, Inc." },
4378     { 346, "Energy Focus, Inc." },
4379     { 347, "Powersmiths International Corp." },
4380     { 348, "Nichibei Co., Ltd." },
4381     { 349, "HKC Technology Ltd." },
4382     { 350, "Ovation Networks, Inc." },
4383     { 351, "Setra Systems" },
4384     { 352, "AVG Automation" },
4385     { 353, "ZXC Ltd." },
4386     { 354, "Byte Sphere" },
4387     { 355, "Generiton Co., Ltd." },
4388     { 356, "Holter Regelarmaturen GmbH & Co. KG" },
4389     { 357, "Bedford Instruments, LLC" },
4390     { 358, "Standair Inc." },
4391     { 359, "WEG Automation - R&D" },
4392     { 360, "Prolon Control Systems ApS" },
4393     { 361, "Inneasoft" },
4394     { 362, "ConneXSoft GmbH" },
4395     { 363, "CEAG Notlichtsysteme GmbH" },
4396     { 364, "Distech Controls Inc." },
4397     { 365, "Industrial Technology Research Institute" },
4398     { 366, "ICONICS, Inc." },
4399     { 367, "IQ Controls s.c." },
4400     { 368, "OJ Electronics A/S" },
4401     { 369, "Rolbit Ltd." },
4402     { 370, "Synapsys Solutions Ltd." },
4403     { 371, "ACME Engineering Prod. Ltd." },
4404     { 372, "Zener Electric Pty, Ltd." },
4405     { 373, "Selectronix, Inc." },
4406     { 374, "Gorbet & Banerjee, LLC." },
4407     { 375, "IME" },
4408     { 376, "Stephen H. Dawson Computer Service" },
4409     { 377, "Accutrol, LLC" },
4410     { 378, "Schneider Elektronik GmbH" },
4411     { 379, "Alpha-Inno Tec GmbH" },
4412     { 380, "ADMMicro, Inc." },
4413     { 381, "Greystone Energy Systems, Inc." },
4414     { 382, "CAP Technologie" },
4415     { 383, "KeRo Systems" },
4416     { 384, "Domat Control System s.r.o." },
4417     { 385, "Efektronics Pty. Ltd." },
4418     { 386, "Hekatron Vertriebs GmbH" },
4419     { 387, "Securiton AG" },
4420     { 388, "Carlo Gavazzi Controls SpA" },
4421     { 389, "Chipkin Automation Systems" },
4422     { 390, "Savant Systems, LLC" },
4423     { 391, "Simmtronic Lighting Controls" },
4424     { 392, "Abelko Innovation AB" },
4425     { 393, "Seresco Technologies Inc." },
4426     { 394, "IT Watchdogs" },
4427     { 395, "Automation Assist Japan Corp." },
4428     { 396, "Thermokon Sensortechnik GmbH" },
4429     { 397, "EGauge Systems, LLC" },
4430     { 398, "Quantum Automation (ASIA) PTE, Ltd." },
4431     { 399, "Toshiba Lighting & Technology Corp." },
4432     { 400, "SPIN Engenharia de Automaca Ltda." },
4433     { 401, "Logistics Systems & Software Services India PVT. Ltd." },
4434     { 402, "Delta Controls Integration Products" },
4435     { 403, "Focus Media" },
4436     { 404, "LUMEnergi Inc." },
4437     { 405, "Kara Systems" },
4438     { 406, "RF Code, Inc." },
4439     { 407, "Fatek Automation Corp." },
4440     { 408, "JANDA Software Company, LLC" },
4441     { 409, "Open System Solutions Limited" },
4442     { 410, "Intelec Systems PTY Ltd." },
4443     { 411, "Ecolodgix, LLC" },
4444     { 412, "Douglas Lighting Controls" },
4445     { 413, "iSAtech GmbH" },
4446     { 414, "AREAL" },
4447     { 415, "Beckhoff Automation GmbH" },
4448     { 416, "IPAS GmbH" },
4449     { 417, "KE2 Therm Solutions" },
4450     { 418, "Base2Products" },
4451     { 419, "DTL Controls, LLC" },
4452     { 420, "INNCOM International, Inc." },
4453     { 421, "BTR Netcom GmbH" },
4454     { 422, "Greentrol Automation, Inc" },
4455     { 423, "BELIMO Automation AG" },
4456     { 424, "Samsung Heavy Industries Co, Ltd" },
4457     { 425, "Triacta Power Technologies, Inc." },
4458     { 426, "Globestar Systems" },
4459     { 427, "MLB Advanced Media, LP" },
4460     { 428, "SWG Stuckmann Wirtschaftliche Gebaudesysteme GmbH" },
4461     { 429, "SensorSwitch" },
4462     { 430, "Multitek Power Limited" },
4463     { 431, "Aquametro AG" },
4464     { 432, "LG Electronics Inc." },
4465     { 433, "Electronic Theatre Controls, Inc." },
4466     { 434, "Mitsubishi Electric Corporation Nagoya Works" },
4467     { 435, "Delta Electronics, Inc." },
4468     { 436, "Elma Kurtalj, Ltd." },
4469     { 437, "ADT Fire and Security Sp. A.o.o." },
4470     { 438, "Nedap Security Management" },
4471     { 439, "ESC Automation Inc." },
4472     { 440, "DSP4YOU Ltd." },
4473     { 441, "GE Sensing and Inspection Technologies" },
4474     { 442, "Embedded Systems SIA" },
4475     { 443, "BEFEGA GmbH" },
4476     { 444, "Baseline Inc." },
4477     { 445, "M2M Systems Integrators" },
4478     { 446, "OEMCtrl" },
4479     { 447, "Clarkson Controls Limited" },
4480     { 448, "Rogerwell Control System Limited" },
4481     { 449, "SCL Elements" },
4482     { 450, "Hitachi Ltd." },
4483     { 451, "Newron System SA" },
4484     { 452, "BEVECO Gebouwautomatisering BV" },
4485     { 453, "Streamside Solutions" },
4486     { 454, "Yellowstone Soft" },
4487     { 455, "Oztech Intelligent Systems Pty Ltd." },
4488     { 456, "Novelan GmbH" },
4489     { 457, "Flexim Americas Corporation" },
4490     { 458, "ICP DAS Co., Ltd." },
4491     { 459, "CARMA Industries Inc." },
4492     { 460, "Log-One Ltd." },
4493     { 461, "TECO Electric & Machinery Co., Ltd." },
4494     { 462, "ConnectEx, Inc." },
4495     { 463, "Turbo DDC Sudwest" },
4496     { 464, "Quatrosense Environmental Ltd." },
4497     { 465, "Fifth Light Technology Ltd." },
4498     { 466, "Scientific Solutions, Ltd." },
4499     { 467, "Controller Area Network Solutions (M) Sdn Bhd" },
4500     { 468, "RESOL - Elektronische Regelungen GmbH" },
4501     { 469, "RPBUS LLC" },
4502     { 470, "BRS Sistemas Eletronicos" },
4503     { 471, "WindowMaster A/S" },
4504     { 472, "Sunlux Technologies Ltd." },
4505     { 473, "Measurlogic" },
4506     { 474, "Frimat GmbH" },
4507     { 475, "Spirax Sarco" },
4508     { 476, "Luxtron" },
4509     { 477, "Raypak Inc" },
4510     { 478, "Air Monitor Corporation" },
4511     { 479, "Regler Och Webbteknik Sverige (ROWS)" },
4512     { 480, "Intelligent Lighting Controls Inc." },
4513     { 481, "Sanyo Electric Industry Co., Ltd" },
4514     { 482, "E-Mon Energy Monitoring Products" },
4515     { 483, "Digital Control Systems" },
4516     { 484, "ATI Airtest Technologies, Inc." },
4517     { 485, "SCS SA" },
4518     { 486, "HMS Industrial Networks AB" },
4519     { 487, "Shenzhen Universal Intellisys Co Ltd" },
4520     { 488, "EK Intellisys Sdn Bhd" },
4521     { 489, "SysCom" },
4522     { 490, "Firecom, Inc." },
4523     { 491, "ESA Elektroschaltanlagen Grimma GmbH" },
4524     { 492, "Kumahira Co Ltd" },
4525     { 493, "Hotraco" },
4526     { 494, "SABO Elektronik GmbH" },
4527     { 495, "Equip'Trans" },
4528     { 496, "TCS Basys Controls" },
4529     { 497, "FlowCon International A/S" },
4530     { 498, "ThyssenKrupp Elevator Americas" },
4531     { 499, "Abatement Technologies" },
4532     { 500, "Continental Control Systems, LLC" },
4533     { 501, "WISAG Automatisierungstechnik GmbH & Co KG" },
4534     { 502, "EasyIO" },
4535     { 503, "EAP-Electric GmbH" },
4536     { 504, "Hardmeier" },
4537     { 505, "Mircom Group of Companies" },
4538     { 506, "Quest Controls" },
4539     { 507, "Mestek, Inc" },
4540     { 508, "Pulse Energy" },
4541     { 509, "Tachikawa Corporation" },
4542     { 510, "University of Nebraska-Lincoln" },
4543     { 511, "Redwood Systems" },
4544     { 512, "PASStec Industrie-Elektronik GmbH" },
4545     { 513, "NgEK, Inc." },
4546     { 514, "FAW Electronics Ltd" },
4547     { 515, "Jireh Energy Tech Co., Ltd." },
4548     { 516, "Enlighted Inc." },
4549     { 517, "El-Piast Sp. Z o.o" },
4550     { 518, "NetxAutomation Software GmbH" },
4551     { 519, "Invertek Drives" },
4552     { 520, "Deutschmann Automation GmbH & Co. KG" },
4553     { 521, "EMU Electronic AG" },
4554     { 522, "Phaedrus Limited" },
4555     { 523, "Sigmatek GmbH & Co KG" },
4556     { 524, "Marlin Controls" },
4557     { 525, "Circutor, SA" },
4558     { 526, "UTC Fire & Security" },
4559     { 527, "DENT Instruments, Inc." },
4560     { 528, "FHP Manufacturing Company - Bosch Group" },
4561     { 529, "GE Intelligent Platforms" },
4562     { 530, "Inner Range Pty Ltd" },
4563     { 531, "GLAS Energy Technology" },
4564     { 532, "MSR-Electronic-GmbH" },
4565     { 533, "Energy Control Systems, Inc." },
4566     { 534, "EMT Controls" },
4567     { 535, "Daintree Networks Inc." },
4568     { 536, "EURO ICC d.o.o" },
4569     { 537, "TE Connectivity Energy" },
4570     { 538, "GEZE GmbH" },
4571     { 539, "NEC Corporation" },
4572     { 540, "Ho Cheung International Company Limited" },
4573     { 541, "Sharp Manufacturing Systems Corporation" },
4574     { 542, "DOT CONTROLS a.s." },
4575     { 543, "BeaconMedaes" },
4576     { 544, "Midea Commercial Aircon" },
4577     { 545, "WattMaster Controls" },
4578     { 546, "Kamstrup A/S" },
4579     { 547, "CA Computer Automation GmbH" },
4580     { 548, "Laars Heating Systems Company" },
4581     { 549, "Hitachi Systems, Ltd." },
4582     { 550, "Fushan AKE Electronic Engineering Co., Ltd." },
4583     { 551, "Toshiba International Corporation" },
4584     { 552, "Starman Systems, LLC" },
4585     { 553, "Samsung Techwin Co., Ltd." },
4586     { 554, "ISAS-Integrated Switchgear and Systems P/L" },
4587     { 556, "Obvius" },
4588     { 557, "Marek Guzik" },
4589     { 558, "Vortek Instruments, LLC" },
4590     { 559, "Universal Lighting Technologies" },
4591     { 560, "Myers Power Products, Inc." },
4592     { 561, "Vector Controls GmbH" },
4593     { 562, "Crestron Electronics, Inc." },
4594     { 563, "A&E Controls Limited" },
4595     { 564, "Projektomontaza A.D." },
4596     { 565, "Freeaire Refrigeration" },
4597     { 566, "Aqua Cooler Pty Limited" },
4598     { 567, "Basic Controls" },
4599     { 568, "GE Measurement and Control Solutions Advanced Sensors" },
4600     { 569, "EQUAL Networks" },
4601     { 570, "Millennial Net" },
4602     { 571, "APLI Ltd" },
4603     { 572, "Electro Industries/GaugeTech" },
4604     { 573, "SangMyung University" },
4605     { 574, "Coppertree Analytics, Inc." },
4606     { 575, "CoreNetiX GmbH" },
4607     { 576, "Acutherm" },
4608     { 577, "Dr. Riedel Automatisierungstechnik GmbH" },
4609     { 578, "Shina System Co., Ltd" },
4610     { 579, "Iqapertus" },
4611     { 580, "PSE Technology" },
4612     { 581, "BA Systems" },
4613     { 582, "BTICINO" },
4614     { 583, "Monico, Inc." },
4615     { 584, "iCue" },
4616     { 585, "tekmar Control Systems Ltd." },
4617     { 586, "Control Technology Corporation" },
4618     { 587, "GFAE GmbH" },
4619     { 588, "BeKa Software GmbH" },
4620     { 589, "Isoil Industria SpA" },
4621     { 590, "Home Systems Consulting SpA" },
4622     { 591, "Socomec" },
4623     { 592, "Everex Communications, Inc." },
4624     { 593, "Ceiec Electric Technology" },
4625     { 594, "Atrila GmbH" },
4626     { 595, "WingTechs" },
4627     { 596, "Shenzhen Mek Intellisys Pte Ltd." },
4628     { 597, "Nestfield Co., Ltd." },
4629     { 598, "Swissphone Telecom AG" },
4630     { 599, "PNTECH JSC" },
4631     { 600, "Horner APG, LLC" },
4632     { 601, "PVI Industries, LLC" },
4633     { 602, "Ela-compil" },
4634     { 603, "Pegasus Automation International LLC" },
4635     { 604, "Wight Electronic Services Ltd." },
4636     { 605, "Marcom" },
4637     { 606, "Exhausto A/S" },
4638     { 607, "Dwyer Instruments, Inc." },
4639     { 608, "Link GmbH" },
4640     { 609, "Oppermann Regelgerate GmbH" },
4641     { 610, "NuAire, Inc." },
4642     { 611, "Nortec Humidity, Inc." },
4643     { 612, "Bigwood Systems, Inc." },
4644     { 613, "Enbala Power Networks" },
4645     { 614, "Inter Energy Co., Ltd." },
4646     { 615, "ETC" },
4647     { 616, "COMELEC S.A.R.L" },
4648     { 617, "Pythia Technologies" },
4649     { 618, "TrendPoint Systems, Inc." },
4650     { 619, "AWEX" },
4651     { 620, "Eurevia" },
4652     { 621, "Kongsberg E-lon AS" },
4653     { 622, "FlaktWoods" },
4654     { 623, "E + E Elektronik GES M.B.H." },
4655     { 624, "ARC Informatique" },
4656     { 625, "SKIDATA AG" },
4657     { 626, "WSW Solutions" },
4658     { 627, "Trefon Electronic GmbH" },
4659     { 628, "Dongseo System" },
4660     { 629, "Kanontec Intelligence Technology Co., Ltd." },
4661     { 630, "EVCO S.p.A." },
4662     { 631, "Accuenergy (CANADA) Inc." },
4663     { 632, "SoftDEL" },
4664     { 633, "Orion Energy Systems, Inc." },
4665     { 634, "Roboticsware" },
4666     { 635, "DOMIQ Sp. z o.o." },
4667     { 636, "Solidyne" },
4668     { 637, "Elecsys Corporation" },
4669     { 638, "Conditionaire International Pty. Limited" },
4670     { 639, "Quebec, Inc." },
4671     { 640, "Homerun Holdings" },
4672     { 641, "RFM, Inc." },
4673     { 642, "Comptek" },
4674     { 643, "Westco Systems, Inc." },
4675     { 644, "Advancis Software & Services GmbH" },
4676     { 645, "Intergrid, LLC" },
4677     { 646, "Markerr Controls, Inc." },
4678     { 647, "Toshiba Elevator and Building Systems Corporation" },
4679     { 648, "Spectrum Controls, Inc." },
4680     { 649, "Mkservice" },
4681     { 650, "Fox Thermal Instruments" },
4682     { 651, "SyxthSense Ltd" },
4683     { 652, "DUHA System S R.O." },
4684     { 653, "NIBE" },
4685     { 654, "Melink Corporation" },
4686     { 655, "Fritz-Haber-Institut" },
4687     { 656, "MTU Onsite Energy GmbH, Gas Power Systems" },
4688     { 657, "Omega Engineering, Inc." },
4689     { 658, "Avelon" },
4690     { 659, "Ywire Technologies, Inc." },
4691     { 660, "M.R. Engineering Co., Ltd." },
4692     { 661, "Lochinvar, LLC" },
4693     { 662, "Sontay Limited" },
4694     { 663, "GRUPA Slawomir Chelminski" },
4695     { 664, "Arch Meter Corporation" },
4696     { 665, "Senva, Inc." },
4697     { 667, "FM-Tec" },
4698     { 668, "Systems Specialists, Inc." },
4699     { 669, "SenseAir" },
4700     { 670, "AB IndustrieTechnik Srl" },
4701     { 671, "Cortland Research, LLC" },
4702     { 672, "MediaView" },
4703     { 673, "VDA Elettronica" },
4704     { 674, "CSS, Inc." },
4705     { 675, "Tek-Air Systems, Inc." },
4706     { 676, "ICDT" },
4707     { 677, "The Armstrong Monitoring Corporation" },
4708     { 678, "DIXELL S.r.l" },
4709     { 679, "Lead System, Inc." },
4710     { 680, "ISM EuroCenter S.A." },
4711     { 681, "TDIS" },
4712     { 682, "Trade FIDES" },
4713     { 683, "Knurr GmbH (Emerson Network Power)" },
4714     { 684, "Resource Data Management" },
4715     { 685, "Abies Technology, Inc." },
4716     { 686, "Amalva" },
4717     { 687, "MIRAE Electrical Mfg. Co., Ltd." },
4718     { 688, "HunterDouglas Architectural Projects Scandinavia ApS" },
4719     { 689, "RUNPAQ Group Co., Ltd" },
4720     { 690, "Unicard SA" },
4721     { 691, "IE Technologies" },
4722     { 692, "Ruskin Manufacturing" },
4723     { 693, "Calon Associates Limited" },
4724     { 694, "Contec Co., Ltd." },
4725     { 695, "iT GmbH"},
4726     { 696, "Autani Corporation"},
4727     { 697, "Christian Fortin"},
4728     { 698, "HDL"},
4729     { 699, "IPID Sp. Z.O.O Limited"},
4730     { 700, "Fuji Electric Co., Ltd"},
4731     { 701, "View, Inc."},
4732     { 702, "Samsung S1 Corporation"},
4733     { 703, "New Lift"},
4734     { 704, "VRT Systems"},
4735     { 0, NULL }
4736 };
4737 static value_string_ext BACnetVendorIdentifiers_ext = VALUE_STRING_EXT_INIT(BACnetVendorIdentifiers);
4738
4739 static int proto_bacapp = -1;
4740 static int hf_bacapp_type = -1;
4741 static int hf_bacapp_pduflags = -1;
4742 static int hf_bacapp_SEG = -1;
4743 static int hf_bacapp_MOR = -1;
4744 static int hf_bacapp_SA = -1;
4745 static int hf_bacapp_response_segments = -1;
4746 static int hf_bacapp_max_adpu_size = -1;
4747 static int hf_bacapp_invoke_id = -1;
4748 static int hf_bacapp_objectType = -1;
4749 static int hf_bacapp_instanceNumber = -1;
4750 static int hf_bacapp_sequence_number = -1;
4751 static int hf_bacapp_window_size = -1;
4752 static int hf_bacapp_service = -1;
4753 static int hf_bacapp_NAK = -1;
4754 static int hf_bacapp_SRV = -1;
4755 static int hf_Device_Instance_Range_Low_Limit = -1;
4756 static int hf_Device_Instance_Range_High_Limit = -1;
4757 static int hf_BACnetRejectReason = -1;
4758 static int hf_BACnetAbortReason = -1;
4759 static int hf_BACnetApplicationTagNumber = -1;
4760 static int hf_BACnetContextTagNumber = -1;
4761 static int hf_BACnetExtendedTagNumber = -1;
4762 static int hf_BACnetNamedTag = -1;
4763 static int hf_BACnetTagClass = -1;
4764 static int hf_BACnetCharacterSet = -1;
4765 static int hf_bacapp_tag_lvt = -1;
4766 static int hf_bacapp_tag_ProcessId = -1;
4767 static int hf_bacapp_uservice = -1;
4768 static int hf_BACnetPropertyIdentifier = -1;
4769 static int hf_BACnetVendorIdentifier = -1;
4770 static int hf_BACnetRestartReason = -1;
4771 static int hf_bacapp_tag_IPV4 = -1;
4772 static int hf_bacapp_tag_IPV6 = -1;
4773 static int hf_bacapp_tag_PORT = -1;
4774 /* some more variables for segmented messages */
4775 static int hf_msg_fragments = -1;
4776 static int hf_msg_fragment = -1;
4777 static int hf_msg_fragment_overlap = -1;
4778 static int hf_msg_fragment_overlap_conflicts = -1;
4779 static int hf_msg_fragment_multiple_tails = -1;
4780 static int hf_msg_fragment_too_long_fragment = -1;
4781 static int hf_msg_fragment_error = -1;
4782 static int hf_msg_fragment_count = -1;
4783 static int hf_msg_reassembled_in = -1;
4784 static int hf_msg_reassembled_length = -1;
4785
4786 static gint ett_msg_fragment = -1;
4787 static gint ett_msg_fragments = -1;
4788
4789 static gint ett_bacapp = -1;
4790 static gint ett_bacapp_control = -1;
4791 static gint ett_bacapp_tag = -1;
4792 static gint ett_bacapp_list = -1;
4793 static gint ett_bacapp_value = -1;
4794
4795 static expert_field ei_bacapp_bad_length = EI_INIT;
4796
4797 static gint32 propertyIdentifier = -1;
4798 static gint32 propertyArrayIndex = -1;
4799 static guint32 object_type = 4096;
4800
4801 static guint8 bacapp_flags = 0;
4802 static guint8 bacapp_seq = 0;
4803
4804 /* Defined to allow vendor identifier registration of private transfer dissectors */
4805 static dissector_table_t bacapp_dissector_table;
4806
4807
4808 /* Stat: BACnet Packets sorted by IP */
4809 bacapp_info_value_t bacinfo;
4810
4811 static const gchar* st_str_packets_by_ip = "BACnet Packets by IP";
4812 static const gchar* st_str_packets_by_ip_dst = "By Destination";
4813 static const gchar* st_str_packets_by_ip_src = "By Source";
4814 static int st_node_packets_by_ip = -1;
4815 static int st_node_packets_by_ip_dst = -1;
4816 static int st_node_packets_by_ip_src = -1;
4817
4818 static void
4819 bacapp_packet_stats_tree_init(stats_tree* st)
4820 {
4821     st_node_packets_by_ip = stats_tree_create_pivot(st, st_str_packets_by_ip, 0);
4822     st_node_packets_by_ip_src = stats_tree_create_node(st, st_str_packets_by_ip_src, st_node_packets_by_ip, TRUE);
4823     st_node_packets_by_ip_dst = stats_tree_create_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, TRUE);
4824 }
4825
4826 static int
4827 bacapp_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4828 {
4829     int    packets_for_this_dst;
4830     int    packets_for_this_src;
4831     int    service_for_this_dst;
4832     int    service_for_this_src;
4833     int    src_for_this_dst;
4834     int    dst_for_this_src;
4835     int    objectid_for_this_dst;
4836     int    objectid_for_this_src;
4837     int    instanceid_for_this_dst;
4838     int    instanceid_for_this_src;
4839     gchar *dststr;
4840     gchar *srcstr;
4841     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4842
4843     srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", ep_address_to_str(&pinfo->src), NULL);
4844     dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", ep_address_to_str(&pinfo->dst), NULL);
4845
4846     tick_stat_node(st, st_str_packets_by_ip, 0, TRUE);
4847     packets_for_this_dst = tick_stat_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, TRUE);
4848     packets_for_this_src = tick_stat_node(st, st_str_packets_by_ip_src, st_node_packets_by_ip, TRUE);
4849     src_for_this_dst     = tick_stat_node(st, dststr, packets_for_this_dst, TRUE);
4850     dst_for_this_src     = tick_stat_node(st, srcstr, packets_for_this_src, TRUE);
4851     service_for_this_src = tick_stat_node(st, dststr, dst_for_this_src, TRUE);
4852     service_for_this_dst = tick_stat_node(st, srcstr, src_for_this_dst, TRUE);
4853     if (binfo->service_type) {
4854         objectid_for_this_dst = tick_stat_node(st, binfo->service_type, service_for_this_dst, TRUE);
4855         objectid_for_this_src = tick_stat_node(st, binfo->service_type, service_for_this_src, TRUE);
4856         if (binfo->object_ident) {
4857             instanceid_for_this_dst = tick_stat_node(st, binfo->object_ident, objectid_for_this_dst, TRUE);
4858             tick_stat_node(st, binfo->instance_ident, instanceid_for_this_dst, FALSE);
4859             instanceid_for_this_src = tick_stat_node(st, binfo->object_ident, objectid_for_this_src, TRUE);
4860             tick_stat_node(st, binfo->instance_ident, instanceid_for_this_src, FALSE);
4861         }
4862     }
4863
4864     return 1;
4865 }
4866
4867 /* Stat: BACnet Packets sorted by Service */
4868 static const gchar* st_str_packets_by_service = "BACnet Packets by Service";
4869 static int st_node_packets_by_service = -1;
4870
4871 static void
4872 bacapp_service_stats_tree_init(stats_tree* st)
4873 {
4874     st_node_packets_by_service = stats_tree_create_pivot(st, st_str_packets_by_service, 0);
4875 }
4876
4877 static int
4878 bacapp_stats_tree_service(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4879 {
4880     int    servicetype;
4881     int    src, dst;
4882     int    objectid;
4883
4884     gchar *dststr;
4885     gchar *srcstr;
4886
4887     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4888
4889     srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", ep_address_to_str(&pinfo->src), NULL);
4890     dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", ep_address_to_str(&pinfo->dst), NULL);
4891
4892     tick_stat_node(st, st_str_packets_by_service, 0, TRUE);
4893     if (binfo->service_type) {
4894         servicetype = tick_stat_node(st, binfo->service_type, st_node_packets_by_service, TRUE);
4895         src         = tick_stat_node(st, srcstr, servicetype, TRUE);
4896         dst         = tick_stat_node(st, dststr, src, TRUE);
4897         if (binfo->object_ident) {
4898             objectid = tick_stat_node(st, binfo->object_ident, dst, TRUE);
4899             tick_stat_node(st, binfo->instance_ident, objectid, FALSE);
4900         }
4901     }
4902
4903     return 1;
4904 }
4905
4906 /* Stat: BACnet Packets sorted by Object Type */
4907 static const gchar* st_str_packets_by_objectid = "BACnet Packets by Object Type";
4908 static int st_node_packets_by_objectid = -1;
4909
4910 static void
4911 bacapp_objectid_stats_tree_init(stats_tree* st)
4912 {
4913     st_node_packets_by_objectid = stats_tree_create_pivot(st, st_str_packets_by_objectid, 0);
4914 }
4915
4916 static int
4917 bacapp_stats_tree_objectid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4918 {
4919     int    servicetype;
4920     int    src, dst;
4921     int    objectid;
4922
4923     gchar *dststr;
4924     gchar *srcstr;
4925     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4926
4927     srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", ep_address_to_str(&pinfo->src), NULL);
4928     dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", ep_address_to_str(&pinfo->dst), NULL);
4929
4930     tick_stat_node(st, st_str_packets_by_objectid, 0, TRUE);
4931     if (binfo->object_ident) {
4932         objectid = tick_stat_node(st, binfo->object_ident, st_node_packets_by_objectid, TRUE);
4933         src = tick_stat_node(st, srcstr, objectid, TRUE);
4934         dst = tick_stat_node(st, dststr, src, TRUE);
4935         if (binfo->service_type) {
4936             servicetype = tick_stat_node(st, binfo->service_type, dst, TRUE);
4937             tick_stat_node(st, binfo->instance_ident, servicetype, FALSE);
4938         }
4939     }
4940
4941     return 1;
4942 }
4943
4944 /* Stat: BACnet Packets sorted by Instance No */
4945 static const gchar* st_str_packets_by_instanceid  = "BACnet Packets by Instance ID";
4946 static int          st_node_packets_by_instanceid = -1;
4947
4948 static void
4949 bacapp_instanceid_stats_tree_init(stats_tree* st)
4950 {
4951     st_node_packets_by_instanceid = stats_tree_create_pivot(st, st_str_packets_by_instanceid, 0);
4952 }
4953
4954 static int
4955 bacapp_stats_tree_instanceid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4956 {
4957     int    servicetype;
4958     int    src, dst;
4959     int    instanceid;
4960
4961     gchar *dststr;
4962     gchar *srcstr;
4963     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4964
4965     srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", ep_address_to_str(&pinfo->src), NULL);
4966     dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", ep_address_to_str(&pinfo->dst), NULL);
4967
4968     tick_stat_node(st, st_str_packets_by_instanceid, 0, TRUE);
4969     if (binfo->object_ident) {
4970         instanceid = tick_stat_node(st, binfo->instance_ident, st_node_packets_by_instanceid, TRUE);
4971         src = tick_stat_node(st, srcstr, instanceid, TRUE);
4972         dst = tick_stat_node(st, dststr, src, TRUE);
4973         if (binfo->service_type) {
4974             servicetype = tick_stat_node(st, binfo->service_type, dst, TRUE);
4975             tick_stat_node(st, binfo->object_ident, servicetype, FALSE);
4976         }
4977     }
4978     return 1;
4979 }
4980
4981
4982 /* register all BACnet Ststistic trees */
4983 static void
4984 register_bacapp_stat_trees(void)
4985 {
4986     stats_tree_register("bacapp", "bacapp_ip", "BACnet/Packets sorted by IP", 0,
4987         bacapp_stats_tree_packet, bacapp_packet_stats_tree_init, NULL);
4988     stats_tree_register("bacapp", "bacapp_service", "BACnet/Packets sorted by Service", 0,
4989         bacapp_stats_tree_service, bacapp_service_stats_tree_init, NULL);
4990     stats_tree_register("bacapp", "bacapp_objectid", "BACnet/Packets sorted by Object Type", 0,
4991         bacapp_stats_tree_objectid, bacapp_objectid_stats_tree_init, NULL);
4992     stats_tree_register("bacapp", "bacapp_instanceid", "BACnet/Packets sorted by Instance ID", 0,
4993         bacapp_stats_tree_instanceid, bacapp_instanceid_stats_tree_init, NULL);
4994 }
4995
4996 /* 'data' must be ep_ allocated */
4997 static gint
4998 updateBacnetInfoValue(gint whichval, const gchar *data)
4999 {
5000     if (whichval == BACINFO_SERVICE) {
5001         bacinfo.service_type = data;
5002         return 0;
5003     }
5004     if (whichval == BACINFO_INVOKEID) {
5005         bacinfo.invoke_id = data;
5006         return 0;
5007     }
5008     if (whichval == BACINFO_OBJECTID) {
5009         bacinfo.object_ident = data;
5010         return 0;
5011     }
5012     if (whichval == BACINFO_INSTANCEID) {
5013         bacinfo.instance_ident = data;
5014         return 0;
5015     }
5016     return -1;
5017 }
5018
5019 static const fragment_items msg_frag_items = {
5020     /* Fragment subtrees */
5021     &ett_msg_fragment,
5022     &ett_msg_fragments,
5023     /* Fragment fields */
5024     &hf_msg_fragments,
5025     &hf_msg_fragment,
5026     &hf_msg_fragment_overlap,
5027     &hf_msg_fragment_overlap_conflicts,
5028     &hf_msg_fragment_multiple_tails,
5029     &hf_msg_fragment_too_long_fragment,
5030     &hf_msg_fragment_error,
5031     &hf_msg_fragment_count,
5032     /* Reassembled in field */
5033     &hf_msg_reassembled_in,
5034     /* Reassembled length field */
5035     &hf_msg_reassembled_length,
5036     /* Reassembled data field */
5037     NULL,
5038     /* Tag */
5039     "Message fragments"
5040 };
5041
5042 #if 0
5043 /* if BACnet uses the reserved values, then patch the corresponding values here, maximum 16 values are defined */
5044 /* FIXME: fGetMaxAPDUSize is commented out, as it is not used. It was used to set variables which were not later used. */
5045 static const guint MaxAPDUSize [] = { 50, 128, 206, 480, 1024, 1476 };
5046
5047 static guint
5048 fGetMaxAPDUSize(guint8 idx)
5049 {
5050     /* only 16 values are defined, so use & 0x0f */
5051     /* check the size of the Array, deliver either the entry
5052        or the first entry if idx is outside of the array (bug 3736 comment#7) */
5053
5054     if ((idx & 0x0f) >= (gint)(sizeof(MaxAPDUSize)/sizeof(guint)))
5055         return MaxAPDUSize[0];
5056     else
5057         return MaxAPDUSize[idx & 0x0f];
5058 }
5059 #endif
5060
5061
5062 /* Used when there are ranges of reserved and proprietary enumerations */
5063 static const char*
5064 val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
5065     const char *fmt, const char *split_fmt)
5066 {
5067     if (val < split_val)
5068         return val_to_str(val, vs, fmt);
5069     else
5070         return val_to_str(val, vs, split_fmt);
5071 }
5072
5073 /* from clause 20.2.1.3.2 Constructed Data */
5074 /* returns true if the extended value is used */
5075 static gboolean
5076 tag_is_extended_value(guint8 tag)
5077 {
5078     return (tag & 0x07) == 5;
5079 }
5080
5081 static gboolean
5082 tag_is_opening(guint8 tag)
5083 {
5084     return (tag & 0x07) == 6;
5085 }
5086
5087 static gboolean
5088 tag_is_closing(guint8 tag)
5089 {
5090     return (tag & 0x07) == 7;
5091 }
5092
5093 /* from clause 20.2.1.1 Class
5094    class bit shall be one for context specific tags */
5095 /* returns true if the tag is context specific */
5096 static gboolean
5097 tag_is_context_specific(guint8 tag)
5098 {
5099     return (tag & 0x08) != 0;
5100 }
5101
5102 static gboolean
5103 tag_is_extended_tag_number(guint8 tag)
5104 {
5105     return ((tag & 0xF0) == 0xF0);
5106 }
5107
5108 static guint32
5109 object_id_type(guint32 object_identifier)
5110 {
5111     return ((object_identifier >> 22) & 0x3FF);
5112 }
5113
5114 static guint32
5115 object_id_instance(guint32 object_identifier)
5116 {
5117     return (object_identifier & 0x3FFFFF);
5118 }
5119
5120 static guint
5121 fTagNo(tvbuff_t *tvb, guint offset)
5122 {
5123     return (guint)(tvb_get_guint8(tvb, offset) >> 4);
5124 }
5125
5126 static gboolean
5127 fUnsigned32(tvbuff_t *tvb, guint offset, guint32 lvt, guint32 *val)
5128 {
5129     gboolean valid = TRUE;
5130
5131     switch (lvt) {
5132     case 1:
5133         *val = tvb_get_guint8(tvb, offset);
5134         break;
5135     case 2:
5136         *val = tvb_get_ntohs(tvb, offset);
5137         break;
5138     case 3:
5139         *val = tvb_get_ntoh24(tvb, offset);
5140         break;
5141     case 4:
5142         *val = tvb_get_ntohl(tvb, offset);
5143         break;
5144     default:
5145         valid = FALSE;
5146         break;
5147     }
5148
5149     return valid;
5150 }
5151
5152 static gboolean
5153 fUnsigned64(tvbuff_t *tvb, guint offset, guint32 lvt, guint64 *val)
5154 {
5155     gboolean valid = FALSE;
5156     gint64   value = 0;
5157     guint8   data, i;
5158
5159     if (lvt && (lvt <= 8)) {
5160         valid = TRUE;
5161         for (i = 0; i < lvt; i++) {
5162             data = tvb_get_guint8(tvb, offset+i);
5163             value = (value << 8) + data;
5164         }
5165         *val = value;
5166     }
5167
5168     return valid;
5169 }
5170
5171 /* BACnet Signed Value uses 2's complement notation, but with a twist:
5172    All signed integers shall be encoded in the smallest number of octets
5173    possible.  That is, the first octet of any multi-octet encoded value
5174    shall not be X'00' if the most significant bit (bit 7) of the second
5175    octet is 0, and the first octet shall not be X'FF' if the most
5176    significant bit of the second octet is 1. ASHRAE-135-2004-20.2.5 */
5177 static gboolean
5178 fSigned64(tvbuff_t *tvb, guint offset, guint32 lvt, gint64 *val)
5179 {
5180     gboolean valid = FALSE;
5181     gint64   value = 0;
5182     guint8   data;
5183     guint32  i;
5184
5185     /* we can only handle 7 bytes for a 64-bit value due to signed-ness */
5186     if (lvt && (lvt <= 7)) {
5187         valid = TRUE;
5188         data = tvb_get_guint8(tvb, offset);
5189         if ((data & 0x80) != 0)
5190             value = (-1 << 8) | data;
5191         else
5192             value = data;
5193         for (i = 1; i < lvt; i++) {
5194             data = tvb_get_guint8(tvb, offset+i);
5195             value = (value << 8) + data;
5196         }
5197         *val = value;
5198     }
5199
5200     return valid;
5201 }
5202
5203 static guint
5204 fTagHeaderTree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5205     guint offset, guint8 *tag_no, guint8* tag_info, guint32 *lvt)
5206 {
5207     proto_item *ti = NULL;
5208     guint8      tag;
5209     guint8      value;
5210     guint       tag_len = 1;
5211     guint       lvt_len = 1;    /* used for tree display of lvt */
5212     guint       lvt_offset;     /* used for tree display of lvt */
5213
5214     lvt_offset = offset;
5215     tag        = tvb_get_guint8(tvb, offset);
5216     *tag_info  = 0;
5217     *lvt       = tag & 0x07;
5218
5219     /* To solve the problem of lvt values of 6/7 being indeterminate - it */
5220     /* can mean open/close tag or length of 6/7 after the length is */
5221     /* computed below - store whole tag info, not just context bit. */
5222     if (tag_is_context_specific(tag)) *tag_info = tag & 0x0F;
5223     *tag_no = tag >> 4;
5224     if (tag_is_extended_tag_number(tag)) {
5225         *tag_no = tvb_get_guint8(tvb, offset + tag_len++);
5226     }
5227     if (tag_is_extended_value(tag)) {       /* length is more than 4 Bytes */
5228         lvt_offset += tag_len;
5229         value = tvb_get_guint8(tvb, lvt_offset);
5230         tag_len++;
5231         if (value == 254) { /* length is encoded with 16 Bits */
5232             *lvt = tvb_get_ntohs(tvb, lvt_offset+1);
5233             tag_len += 2;
5234             lvt_len += 2;
5235         } else if (value == 255) { /* length is encoded with 32 Bits */
5236             *lvt = tvb_get_ntohl(tvb, lvt_offset+1);
5237             tag_len += 4;
5238             lvt_len += 4;
5239         } else
5240             *lvt = value;
5241     }
5242
5243     if (tree) {
5244         proto_tree *subtree;
5245         if (tag_is_opening(tag))
5246             ti = proto_tree_add_text(tree, tvb, offset, tag_len, "{[%u]", *tag_no );
5247         else if (tag_is_closing(tag))
5248             ti = proto_tree_add_text(tree, tvb, offset, tag_len, "}[%u]", *tag_no );
5249         else if (tag_is_context_specific(tag)) {
5250             ti = proto_tree_add_text(tree, tvb, offset, tag_len,
5251                                      "Context Tag: %u, Length/Value/Type: %u",
5252                                      *tag_no, *lvt);
5253         } else
5254             ti = proto_tree_add_text(tree, tvb, offset, tag_len,
5255                                      "Application Tag: %s, Length/Value/Type: %u",
5256                                      val_to_str(*tag_no,
5257                                                 BACnetApplicationTagNumber,
5258                                                 ASHRAE_Reserved_Fmt),
5259                                      *lvt);
5260
5261         /* details if needed */
5262         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5263         proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, ENC_BIG_ENDIAN);
5264         if (tag_is_extended_tag_number(tag)) {
5265             proto_tree_add_uint_format(subtree,
5266                                        hf_BACnetContextTagNumber,
5267                                        tvb, offset, 1, tag,
5268                                        "Extended Tag Number");
5269             proto_tree_add_item(subtree,
5270                                 hf_BACnetExtendedTagNumber,
5271                                 tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5272         } else {
5273             if (tag_is_context_specific(tag))
5274                 proto_tree_add_item(subtree,
5275                                     hf_BACnetContextTagNumber,
5276                                     tvb, offset, 1, ENC_BIG_ENDIAN);
5277             else
5278                 proto_tree_add_item(subtree,
5279                                     hf_BACnetApplicationTagNumber,
5280                                     tvb, offset, 1, ENC_BIG_ENDIAN);
5281         }
5282         if (tag_is_closing(tag) || tag_is_opening(tag))
5283             proto_tree_add_item(subtree,
5284                                 hf_BACnetNamedTag,
5285                                 tvb, offset, 1, ENC_BIG_ENDIAN);
5286         else if (tag_is_extended_value(tag)) {
5287             proto_tree_add_item(subtree,
5288                                 hf_BACnetNamedTag,
5289                                 tvb, offset, 1, ENC_BIG_ENDIAN);
5290             proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
5291                                 tvb, lvt_offset, lvt_len, *lvt);
5292         } else
5293             proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
5294                                 tvb, lvt_offset, lvt_len, *lvt);
5295     } /* if (tree) */
5296
5297     if (*lvt > tvb_length(tvb)) {
5298         expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
5299                                "LVT length too long: %d > %d", *lvt,
5300                                tvb_length(tvb));
5301         *lvt = 1;
5302     }
5303
5304     return tag_len;
5305 }
5306
5307 static guint
5308 fTagHeader(tvbuff_t *tvb, packet_info *pinfo, guint offset, guint8 *tag_no, guint8* tag_info,
5309     guint32 *lvt)
5310 {
5311     return fTagHeaderTree(tvb, pinfo, NULL, offset, tag_no, tag_info, lvt);
5312 }
5313
5314 static guint
5315 fNullTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5316 {
5317     guint8      tag_no, tag_info;
5318     guint32     lvt;
5319     proto_item *ti;
5320     proto_tree *subtree;
5321
5322     ti      = proto_tree_add_text(tree, tvb, offset, 1, "%sNULL", label);
5323     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5324     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5325
5326     return offset + 1;
5327 }
5328
5329 static guint
5330 fBooleanTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5331 {
5332     guint8      tag_no, tag_info;
5333     guint32     lvt      = 0;
5334     proto_item *ti;
5335     proto_tree *subtree;
5336     guint       bool_len = 1;
5337
5338     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5339     if (tag_info && lvt == 1) {
5340         lvt = tvb_get_guint8(tvb, offset+1);
5341         ++bool_len;
5342     }
5343
5344     ti = proto_tree_add_text(tree, tvb, offset, bool_len,
5345                              "%s%s", label, lvt == 0 ? "FALSE" : "TRUE");
5346     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5347     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5348
5349     return offset + bool_len;
5350 }
5351
5352 static guint
5353 fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5354 {
5355     guint64     val = 0;
5356     guint8      tag_no, tag_info;
5357     guint32     lvt;
5358     guint       tag_len;
5359     proto_item *ti;
5360     proto_tree *subtree;
5361
5362     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5363     /* only support up to an 8 byte (64-bit) integer */
5364     if (fUnsigned64(tvb, offset + tag_len, lvt, &val))
5365         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5366             "%s(Unsigned) %" G_GINT64_MODIFIER "u", label, val);
5367     else
5368         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5369             "%s - %u octets (Unsigned)", label, lvt);
5370     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5371     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5372
5373     return offset+tag_len+lvt;
5374 }
5375
5376 static guint
5377 fDevice_Instance(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, int hf)
5378 {
5379     guint8      tag_no, tag_info;
5380     guint32     lvt, safe_lvt;
5381     guint       tag_len;
5382     proto_item *ti;
5383     proto_tree *subtree;
5384
5385     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5386
5387     if (lvt > 4)
5388         safe_lvt = 4;
5389     else
5390         safe_lvt = lvt;
5391
5392     ti = proto_tree_add_item(tree, hf, tvb, offset+tag_len, safe_lvt, ENC_BIG_ENDIAN);
5393
5394     if (lvt != safe_lvt)
5395         expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
5396                 "This field claims to be an impossible %u bytes, while the max is %u", lvt, safe_lvt);
5397
5398     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5399     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5400
5401     return offset+tag_len+lvt;
5402 }
5403
5404 /* set split_val to zero when not needed */
5405 static guint
5406 fEnumeratedTagSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5407     guint offset, const gchar *label, const value_string *vs, guint32 split_val)
5408 {
5409     guint32     val = 0;
5410     guint8      tag_no, tag_info;
5411     guint32     lvt;
5412     guint       tag_len;
5413     proto_item *ti;
5414     proto_tree *subtree;
5415
5416     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5417     /* only support up to a 4 byte (32-bit) enumeration */
5418     if (fUnsigned32(tvb, offset+tag_len, lvt, &val)) {
5419         if (vs)
5420             ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5421                 "%s %s", label, val_to_split_str(val, split_val, vs,
5422                 ASHRAE_Reserved_Fmt, Vendor_Proprietary_Fmt));
5423         else
5424             ti =proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5425                 "%s %u", label, val);
5426     } else {
5427         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5428             "%s - %u octets (enumeration)", label, lvt);
5429     }
5430     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5431     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5432
5433     return offset+tag_len+lvt;
5434 }
5435
5436 static guint
5437 fEnumeratedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5438         guint offset, const gchar *label, const value_string *vs)
5439 {
5440     return fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, vs, 0);
5441 }
5442
5443 static guint
5444 fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5445 {
5446     gint64      val = 0;
5447     guint8      tag_no, tag_info;
5448     guint32     lvt;
5449     guint       tag_len;
5450     proto_item *ti;
5451     proto_tree *subtree;
5452
5453     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5454     if (fSigned64(tvb, offset + tag_len, lvt, &val))
5455         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5456             "%s(Signed) %" G_GINT64_MODIFIER "d", label, val);
5457     else
5458         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5459             "%s - %u octets (Signed)", label, lvt);
5460     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5461     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5462
5463     return offset+tag_len+lvt;
5464 }
5465
5466 static guint
5467 fRealTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5468 {
5469     guint8      tag_no, tag_info;
5470     guint32     lvt;
5471     guint       tag_len;
5472     gfloat      f_val;
5473     proto_item *ti;
5474     proto_tree *subtree;
5475
5476     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5477     f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
5478     ti = proto_tree_add_text(tree, tvb, offset, 4+tag_len,
5479         "%s%f (Real)", label, f_val);
5480     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5481     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5482
5483     return offset+tag_len+4;
5484 }
5485
5486 static guint
5487 fDoubleTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5488 {
5489     guint8 tag_no, tag_info;
5490     guint32 lvt;
5491     guint tag_len;
5492     gdouble d_val;
5493     proto_item *ti;
5494     proto_tree *subtree;
5495
5496     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5497     d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
5498     ti = proto_tree_add_text(tree, tvb, offset, 8+tag_len,
5499         "%s%f (Double)", label, d_val);
5500     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5501     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5502
5503     return offset+tag_len+8;
5504 }
5505
5506 static guint
5507 fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5508 {
5509     guint32     val = 0, lvt;
5510     guint8      tag_no, tag_info;
5511     proto_item *ti;
5512     proto_tree *subtree;
5513     guint       tag_len;
5514
5515     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5516     if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
5517         ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
5518             tvb, offset, lvt+tag_len, val);
5519     else
5520         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5521             "Process Identifier - %u octets (Signed)", lvt);
5522     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5523     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5524     offset += tag_len + lvt;
5525
5526     return offset;
5527 }
5528
5529 static guint
5530 fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5531 {
5532     guint32     val = 0, lvt;
5533     guint8      tag_no, tag_info;
5534     proto_item *ti;
5535     proto_tree *subtree;
5536     guint       tag_len;
5537
5538     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5539     if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
5540         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5541         "%s (hh.mm.ss): %d.%02d.%02d%s",
5542         label,
5543         (val / 3600), ((val % 3600) / 60), (val % 60),
5544         val == 0 ? " (indefinite)" : "");
5545     else
5546         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5547             "%s - %u octets (Signed)", label, lvt);
5548     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5549     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5550
5551     return offset+tag_len+lvt;
5552 }
5553
5554 static guint
5555 fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5556 {
5557     guint32     month, weekOfMonth, dayOfWeek;
5558     guint8      tag_no, tag_info;
5559     guint32     lvt;
5560     guint       tag_len;
5561     proto_item *ti;
5562     proto_tree *subtree;
5563
5564     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5565     month = tvb_get_guint8(tvb, offset+tag_len);
5566     weekOfMonth = tvb_get_guint8(tvb, offset+tag_len+1);
5567     dayOfWeek = tvb_get_guint8(tvb, offset+tag_len+2);
5568     ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s %s, %s",
5569                  val_to_str(month, months, "month (%d) not found"),
5570                  val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"),
5571                  val_to_str(dayOfWeek, day_of_week, "day of week (%d) not found"));
5572     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5573     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5574
5575     return offset+tag_len+lvt;
5576 }
5577
5578 static guint
5579 fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5580 {
5581     guint32     year, month, day, weekday;
5582     guint8      tag_no, tag_info;
5583     guint32     lvt;
5584     guint       tag_len;
5585     proto_item *ti;
5586     proto_tree *subtree;
5587
5588     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5589     year    = tvb_get_guint8(tvb, offset+tag_len);
5590     month   = tvb_get_guint8(tvb, offset+tag_len+1);
5591     day     = tvb_get_guint8(tvb, offset+tag_len+2);
5592     weekday = tvb_get_guint8(tvb, offset+tag_len+3);
5593     if ((year == 255) && (day == 255) && (month == 255) && (weekday == 255)) {
5594         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5595             "%sany", label);
5596     }
5597     else if (year != 255) {
5598         year += 1900;
5599         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5600             "%s%s %d, %d, (Day of Week = %s)",
5601             label, val_to_str(month,
5602                 months,
5603                 "month (%d) not found"),
5604             day, year, val_to_str(weekday,
5605                 day_of_week,
5606                 "(%d) not found"));
5607     } else {
5608         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5609             "%s%s %d, any year, (Day of Week = %s)",
5610             label, val_to_str(month, months, "month (%d) not found"),
5611             day, val_to_str(weekday, day_of_week, "(%d) not found"));
5612     }
5613     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5614     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5615
5616     return offset+tag_len+lvt;
5617 }
5618
5619 static guint
5620 fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5621 {
5622     guint32     hour, minute, second, msec, lvt;
5623     guint8      tag_no, tag_info;
5624     guint       tag_len;
5625     proto_item *ti;
5626     proto_tree *subtree;
5627
5628     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5629     hour    = tvb_get_guint8(tvb, offset+tag_len);
5630     minute  = tvb_get_guint8(tvb, offset+tag_len+1);
5631     second  = tvb_get_guint8(tvb, offset+tag_len+2);
5632     msec    = tvb_get_guint8(tvb, offset+tag_len+3);
5633     if ((hour == 255) && (minute == 255) && (second == 255) && (msec == 255))
5634         ti = proto_tree_add_text(tree, tvb, offset,
5635             lvt+tag_len, "%sany", label);
5636     else
5637         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5638             "%s%d:%02d:%02d.%d %s = %02d:%02d:%02d.%d",
5639             label,
5640             hour > 12 ? hour - 12 : hour,
5641             minute, second, msec,
5642             hour >= 12 ? "P.M." : "A.M.",
5643             hour, minute, second, msec);
5644     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5645     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5646
5647     return offset+tag_len+lvt;
5648 }
5649
5650 static guint
5651 fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5652 {
5653     proto_tree *subtree = tree;
5654     proto_item *tt;
5655
5656     if (label != NULL) {
5657         tt = proto_tree_add_text(subtree, tvb, offset, 10, "%s", label);
5658         subtree = proto_item_add_subtree(tt, ett_bacapp_value);
5659     }
5660     offset = fDate(tvb, pinfo, subtree, offset, "Date: ");
5661     return fTime(tvb, pinfo, subtree, offset, "Time: ");
5662 }
5663
5664 static guint
5665 fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5666 {
5667     guint lastoffset = 0;
5668     guint8 tag_no, tag_info;
5669     guint32 lvt;
5670
5671     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
5672         lastoffset = offset;
5673         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5674         if (tag_is_closing(tag_info)) {   /* closing Tag, but not for me */
5675             return offset;
5676         }
5677         offset = fTime(tvb, pinfo, tree, offset, "Time: ");
5678         offset = fApplicationTypes(tvb, pinfo, tree, offset, "Value: ");
5679
5680         if (offset == lastoffset) break;    /* exit loop if nothing happens inside */
5681     }
5682     return offset;
5683 }
5684
5685 static guint
5686 fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5687 {
5688     guint8  tag_no, tag_info;
5689     guint32 lvt;
5690
5691     switch (fTagNo(tvb, offset)) {
5692     case 0: /* Date */
5693         offset = fDate(tvb, pinfo, tree, offset, "Date: ");
5694         break;
5695     case 1: /* dateRange */
5696         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5697         offset  = fDateRange(tvb, pinfo, tree, offset);
5698         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5699         break;
5700     case 2: /* BACnetWeekNDay */
5701         offset = fWeekNDay(tvb, pinfo, tree, offset);
5702         break;
5703     default:
5704         return offset;
5705     }
5706
5707     return offset;
5708 }
5709
5710 static guint
5711 fEventTimeStamps( tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
5712 {
5713     guint32     lvt     = 0;
5714     proto_tree* subtree = tree;
5715     proto_item* ti      = 0;
5716
5717     if (tvb_reported_length_remaining(tvb, offset) > 0) {
5718         ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventTimeStamps");
5719         if (ti) {
5720             subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5721         }
5722         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
5723         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
5724         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
5725     }
5726     return offset;
5727 }
5728
5729 static guint
5730 fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5731 {
5732     guint8  tag_no = 0, tag_info = 0;
5733     guint32 lvt    = 0;
5734
5735     if (tvb_reported_length_remaining(tvb, offset) > 0) {   /* don't loop, it's a CHOICE */
5736         switch (fTagNo(tvb, offset)) {
5737         case 0: /* time */
5738             offset = fTime(tvb, pinfo, tree, offset, label?label:"time: ");
5739             break;
5740         case 1: /* sequenceNumber */
5741             offset = fUnsignedTag(tvb, pinfo, tree, offset,
5742                 label?label:"sequence number: ");
5743             break;
5744         case 2: /* dateTime */
5745             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5746             offset  = fDateTime(tvb, pinfo, tree, offset, label?label:"date time: ");
5747             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5748             break;
5749         default:
5750             return offset;
5751         }
5752     }
5753
5754     return offset;
5755 }
5756
5757
5758 static guint
5759 fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5760 {
5761     if (tvb_reported_length_remaining(tvb, offset) > 0) {
5762         offset = fApplicationTypes(tvb, pinfo, tree, offset, "increment: ");
5763     }
5764     return offset;
5765 }
5766
5767 static const value_string
5768 BACnetDaysOfWeek [] = {
5769     { 0, "Monday" },
5770     { 1, "Tuesday" },
5771     { 2, "Wednesday" },
5772     { 3, "Thursday" },
5773     { 4, "Friday" },
5774     { 5, "Saturday" },
5775     { 6, "Sunday" },
5776     { 0, NULL }
5777 };
5778
5779 static guint
5780 fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5781 {
5782     if (tvb_reported_length_remaining(tvb, offset) > 0) {
5783         offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
5784                                              "valid Days: ", BACnetDaysOfWeek);
5785         offset = fTime(tvb, pinfo, tree, offset, "from time: ");
5786         offset = fTime(tvb, pinfo, tree, offset, "to time: ");
5787         offset = fRecipient(tvb, pinfo, tree, offset);
5788         offset = fProcessId(tvb, pinfo, tree, offset);
5789         offset = fApplicationTypes(tvb, pinfo, tree, offset,
5790                                     "issue confirmed notifications: ");
5791         offset = fBitStringTagVS(tvb, pinfo, tree, offset,
5792                                   "transitions: ", BACnetEventTransitionBits);
5793     }
5794     return offset;
5795 }
5796
5797
5798 static guint
5799 fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
5800 {
5801     gchar      *tmp;
5802     guint       start   = offset;
5803     guint8      tag_no, tag_info;
5804     proto_tree *subtree = tree;
5805     proto_item *ti      = 0;
5806
5807     offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5808
5809     if (lvt > 0) {
5810         tmp = tvb_bytes_to_ep_str(tvb, offset, lvt);
5811         ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s %s", label, tmp);
5812         offset += lvt;
5813     }
5814
5815     if (ti)
5816         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5817
5818     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
5819
5820     return offset;
5821 }
5822
5823 static guint
5824 fMacAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
5825 {
5826     gchar *tmp;
5827     guint start = offset;
5828     guint8 tag_no, tag_info;
5829     proto_tree* subtree = tree;
5830     proto_item* ti;
5831
5832     offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5833
5834     ti = proto_tree_add_text(tree, tvb, offset, 6, "%s", label); /* just add the label, with the tagHeader information in its subtree */
5835
5836     if (lvt > 0) {
5837         if (lvt == 6) { /* we have 6 Byte IP Address with 4 Octets IPv4 and 2 Octets Port Information */
5838
5839             guint32 ip   = tvb_get_ipv4(tvb, offset);
5840             guint16 port = tvb_get_ntohs(tvb, offset+4);
5841
5842             proto_tree_add_ipv4(tree, hf_bacapp_tag_IPV4, tvb, offset, 4, ip);
5843             proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+4, 2, port);
5844
5845         } else {
5846             if (lvt == 18) { /* we have 18 Byte IP Address with 16 Octets IPv6 and 2 Octets Port Information */
5847             struct e_in6_addr addr;
5848             guint16 port =  tvb_get_ntohs(tvb, offset+16);
5849             tvb_get_ipv6(tvb, offset, &addr);
5850
5851             proto_tree_add_ipv6(tree, hf_bacapp_tag_IPV6, tvb, offset, 16, (const guint8 *) &addr);
5852             proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+16, 2, port);
5853
5854             } else { /* we have 1 Byte MS/TP Address or anything else interpreted as an address */
5855                 tmp = tvb_bytes_to_ep_str(tvb, offset, lvt);
5856                 ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s", tmp);
5857             }
5858         }
5859         offset += lvt;
5860     }
5861
5862     if (ti)
5863         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5864
5865     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
5866
5867     return offset;
5868 }
5869
5870 static guint
5871 fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5872 {
5873     guint8  tag_no, tag_info;
5874     guint32 lvt;
5875     guint   offs;
5876
5877     offset = fUnsignedTag(tvb, pinfo, tree, offset, "network-number");
5878     offs   = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5879     if (lvt == 0) {
5880         proto_tree_add_text(tree, tvb, offset, offs, "MAC-address: broadcast");
5881         offset += offs;
5882     } else
5883         offset  = fMacAddress(tvb, pinfo, tree, offset, "MAC-address: ", lvt);
5884
5885     return offset;
5886 }
5887
5888 static guint
5889 fSessionKey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5890 {
5891     offset = fOctetString(tvb, pinfo, tree, offset, "session key: ", 8);
5892     return fAddress(tvb, pinfo, tree, offset);
5893 }
5894
5895 static guint
5896 fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5897 {
5898     guint8      tag_no, tag_info;
5899     guint32     lvt;
5900     guint       tag_length;
5901     proto_item *ti;
5902     proto_tree *subtree;
5903     guint32     object_id;
5904
5905     tag_length  = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5906     object_id   = tvb_get_ntohl(tvb, offset+tag_length);
5907     object_type = object_id_type(object_id);
5908     ti = proto_tree_add_text(tree, tvb, offset, tag_length + 4,
5909         "ObjectIdentifier: %s, %u",
5910         val_to_split_str(object_type,
5911             128,
5912             BACnetObjectType,
5913             ASHRAE_Reserved_Fmt,
5914             Vendor_Proprietary_Fmt),
5915         object_id_instance(object_id));
5916     if (col_get_writable(pinfo->cinfo))
5917         col_append_fstr(pinfo->cinfo, COL_INFO, "%s,%u ",
5918             val_to_split_str(object_type,
5919                 128,
5920                 BACnetObjectType,
5921                 ASHRAE_Reserved_Fmt,
5922                 Vendor_Proprietary_Fmt),
5923                 object_id_instance(object_id));
5924
5925     /* update BACnet Statistics */
5926     updateBacnetInfoValue(BACINFO_OBJECTID,
5927                   wmem_strdup(wmem_packet_scope(),
5928                     val_to_split_str(object_type, 128,
5929                     BACnetObjectType, ASHRAE_Reserved_Fmt,
5930                     Vendor_Proprietary_Fmt)));
5931     updateBacnetInfoValue(BACINFO_INSTANCEID,
5932                   wmem_strdup_printf(wmem_packet_scope(),
5933                     "Instance ID: %u",
5934                     object_id_instance(object_id)));
5935
5936     /* here are the details of how we arrived at the above text */
5937     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5938     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5939     offset += tag_length;
5940     proto_tree_add_item(subtree, hf_bacapp_objectType, tvb, offset, 4, ENC_BIG_ENDIAN);
5941     proto_tree_add_item(subtree, hf_bacapp_instanceNumber, tvb, offset, 4, ENC_BIG_ENDIAN);
5942     offset += 4;
5943
5944     return offset;
5945 }
5946
5947 static guint
5948 fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5949 {
5950     guint8  tag_no, tag_info;
5951     guint32 lvt;
5952
5953     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5954     if (tag_no < 2) {
5955         if (tag_no == 0) { /* device */
5956             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
5957         }
5958         else {  /* address */
5959             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5960             offset  = fAddress(tvb, pinfo, tree, offset);
5961             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5962         }
5963     }
5964     return offset;
5965 }
5966
5967 static guint
5968 fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5969 {
5970     guint       lastoffset = 0;
5971     guint8      tag_no, tag_info;
5972     guint32     lvt;
5973     proto_tree *orgtree    = tree;
5974     proto_item *tt;
5975     proto_tree *subtree;
5976
5977     /* beginning of new item - indent and label */
5978     tt   = proto_tree_add_text(orgtree, tvb, offset, 1, "Recipient Process" );
5979     tree = proto_item_add_subtree(tt, ett_bacapp_value);
5980
5981     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
5982         lastoffset = offset;
5983
5984         switch (fTagNo(tvb, offset)) {
5985         case 0: /* recipient */
5986             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
5987             tt = proto_tree_add_text(tree, tvb, offset, 1, "Recipient");    /* add tree label and indent */
5988             subtree = proto_item_add_subtree(tt, ett_bacapp_value);
5989             offset  = fRecipient(tvb, pinfo, subtree, offset);
5990             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
5991             break;
5992         case 1: /* processId */
5993             offset = fProcessId(tvb, pinfo, tree, offset);
5994             lastoffset = offset;
5995             break;
5996         default:
5997             break;
5998         }
5999         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6000     }
6001     return offset;
6002 }
6003
6004 static guint
6005 fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6006 {
6007     guint       lastoffset = 0;
6008     guint8      tag_no, tag_info;
6009     guint32     lvt;
6010     proto_tree *subtree;
6011     proto_item *tt;
6012     proto_tree *orgtree    = tree;
6013     guint       itemno     = 1;
6014
6015     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6016         lastoffset = offset;
6017         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6018         if (tag_is_closing(tag_info) ) {
6019             return offset;
6020         }
6021         switch (tag_no) {
6022
6023         case 0: /* recipient */
6024                 /* beginning of new item in list */
6025                 tt = proto_tree_add_text(orgtree, tvb, offset, 1, "Subscription %d",itemno);    /* add tree label and indent */
6026                 itemno = itemno + 1;
6027                 tree = proto_item_add_subtree(tt, ett_bacapp_value);
6028
6029                 tt = proto_tree_add_text(tree, tvb, offset, 1, "Recipient");    /* add tree label and indent */
6030                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
6031                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
6032                 offset  = fRecipientProcess(tvb, pinfo, subtree, offset);
6033                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);  /* show context close */
6034             break;
6035         case 1: /* MonitoredPropertyReference */
6036                 tt = proto_tree_add_text(tree, tvb, offset, 1, "Monitored Property Reference");
6037                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
6038                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6039                 offset  = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
6040                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6041             break;
6042         case 2: /* IssueConfirmedNotifications - boolean */
6043             offset = fBooleanTag(tvb, pinfo, tree, offset, "Issue Confirmed Notifications: ");
6044             break;
6045         case 3: /* TimeRemaining */
6046             offset = fUnsignedTag(tvb, pinfo, tree, offset, "Time Remaining: ");
6047             break;
6048         case 4: /* COVIncrement */
6049             offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
6050             break;
6051         default:
6052             break;
6053         }
6054         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6055     }
6056     return offset;
6057 }
6058
6059 static guint
6060 fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6061 {
6062     offset = fObjectIdentifier(tvb, pinfo, tree, offset);
6063     return fAddress(tvb, pinfo, tree, offset);
6064 }
6065
6066 static guint
6067 fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match)
6068 {
6069     guint       lastoffset = 0, len;
6070     guint8      tag_no, tag_info;
6071     guint32     lvt;
6072     proto_tree *subtree    = tree;
6073
6074     /* set the optional global properties to indicate not-used */
6075     propertyArrayIndex = -1;
6076     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6077         lastoffset = offset;
6078         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6079         if (tag_is_closing(tag_info) ) {
6080             if (tag_no == tag_match) {
6081                 return offset;
6082             }
6083             offset += len;
6084             subtree = tree;
6085             continue;
6086         }
6087         switch (tag_no) {
6088
6089         case 0: /* deviceIdentifier */
6090             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
6091             break;
6092         case 1: /* objectIdentifier */
6093             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
6094             break;
6095         case 2: /* propertyIdentifier */
6096             offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
6097             break;
6098         case 3: /* propertyArrayIndex */
6099             offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
6100             break;
6101         case 4: /* propertyValue */
6102             offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
6103             break;
6104         case 5: /* priority */
6105             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
6106             break;
6107         case 6: /* postDelay */
6108             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Post Delay: ");
6109             break;
6110         case 7: /* quitOnFailure */
6111             offset = fBooleanTag(tvb, pinfo, subtree, offset,
6112                 "Quit On Failure: ");
6113             break;
6114         case 8: /* writeSuccessful */
6115             offset = fBooleanTag(tvb, pinfo, subtree, offset,
6116                 "Write Successful: ");
6117             break;
6118         default:
6119             return offset;
6120         }
6121         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6122     }
6123     return offset;
6124 }
6125
6126 /* BACnetActionList ::= SEQUENCE{
6127       action [0] SEQUENCE OF BACnetActionCommand
6128       }
6129 */
6130 static guint
6131 fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6132 {
6133     guint       lastoffset = 0, len;
6134     guint8      tag_no, tag_info;
6135     guint32     lvt;
6136     proto_tree *subtree    = tree;
6137     proto_item *ti;
6138
6139     while (tvb_reported_length_remaining(tvb, offset) > 0) {
6140         lastoffset = offset;
6141         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6142         if (tag_is_closing(tag_info)) {
6143             subtree = tree;
6144             if ( tag_no != 0 ) /* don't eat the closing property tag, just return */
6145                 return offset;
6146             offset += len;
6147             continue;
6148         }
6149         if (tag_is_opening(tag_info)) {
6150             ti = proto_tree_add_text(tree, tvb, offset, 1, "Action List");
6151             subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6152             offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
6153                 &tag_no, &tag_info, &lvt);
6154         }
6155         switch (tag_no) {
6156         case 0: /* BACnetActionCommand */
6157             offset = fActionCommand(tvb, pinfo, subtree, offset, tag_no);
6158             break;
6159         default:
6160             break;
6161         }
6162         if (offset == lastoffset) break;    /* nothing happened, exit loop */
6163     }
6164     return offset;
6165 }
6166
6167 static guint
6168 fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6169 {
6170     guint8       tag_no, tag_info;
6171     guint32      lvt;
6172     guint        tag_len;
6173     proto_item  *ti;
6174     proto_tree  *subtree;
6175     const gchar *label = "Property Identifier";
6176
6177     propertyIdentifier = 0; /* global Variable */
6178     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6179     /* can we decode this value? */
6180     if (fUnsigned32(tvb, offset+tag_len, lvt, (guint32 *)&propertyIdentifier)) {
6181         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
6182             "%s: %s (%u)", label,
6183             val_to_split_str(propertyIdentifier, 512,
6184                 BACnetPropertyIdentifier,
6185                 ASHRAE_Reserved_Fmt,
6186                 Vendor_Proprietary_Fmt), propertyIdentifier);
6187         if (col_get_writable(pinfo->cinfo))
6188             col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
6189                 val_to_split_str(propertyIdentifier, 512,
6190                     BACnetPropertyIdentifier,
6191                     ASHRAE_Reserved_Fmt,
6192                     Vendor_Proprietary_Fmt));
6193     } else {
6194         /* property identifiers cannot be larger than 22-bits */
6195         return offset;
6196     }
6197     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6198     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6199     proto_tree_add_item(subtree, hf_BACnetPropertyIdentifier, tvb,
6200         offset+tag_len, lvt, ENC_BIG_ENDIAN);
6201
6202     return offset+tag_len+lvt;
6203 }
6204
6205 static guint
6206 fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6207 {
6208     guint8      tag_no, tag_info;
6209     guint32     lvt;
6210     guint       tag_len;
6211     proto_item *ti;
6212     proto_tree *subtree;
6213
6214     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6215     if (fUnsigned32(tvb, offset + tag_len, lvt, (guint32 *)&propertyArrayIndex))
6216         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
6217             "property Array Index (Unsigned) %u", propertyArrayIndex);
6218     else
6219         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
6220             "property Array Index - %u octets (Unsigned)", lvt);
6221     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6222     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6223
6224     return offset+tag_len+lvt;
6225 }
6226
6227 static guint
6228 fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6229 {
6230     guint8      tag_no, tag_info, character_set;
6231     guint32     lvt, l;
6232     guint       offs, extra = 1;
6233     const char *coding;
6234     guint8      bf_arr[512], *out = &bf_arr[0];
6235     proto_item *ti;
6236     proto_tree *subtree;
6237     guint       start = offset;
6238
6239     if (tvb_reported_length_remaining(tvb, offset) > 0) {
6240
6241         offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6242
6243         character_set = tvb_get_guint8(tvb, offset+offs);
6244         /* Account for code page if DBCS */
6245         if (character_set == 1) {
6246             extra = 3;
6247         }
6248         offset += (offs+extra);
6249         lvt -= (extra);
6250
6251         do {
6252             l = MIN(lvt, 256);
6253             /*
6254              * XXX - are we guaranteed that these encoding
6255              * names correspond, on *all* platforms with
6256              * iconv(), to the encodings we want?
6257              * If not (and perhaps even if so), we should
6258              * perhaps have our own iconv() implementation,
6259              * with a different name, so that we control the
6260              * encodings it supports and the names of those
6261              * encodings.
6262              *
6263              * We should also handle that in the general
6264              * string handling code, rather than making it
6265              * specific to the BACAPP dissector, as many
6266              * other dissectors need to handle various
6267              * character encodings.
6268              */
6269             /** this decoding may be not correct for multi-byte characters, Lka */
6270             switch (character_set) {
6271             case ANSI_X3_4:
6272                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_UTF_8);
6273                 coding = "UTF-8";
6274                 break;
6275             case IBM_MS_DBCS:
6276                 out = tvb_get_string(wmem_packet_scope(), tvb, offset, l);
6277                 coding = "IBM MS DBCS";
6278                 break;
6279             case JIS_C_6226:
6280                 out = tvb_get_string(wmem_packet_scope(), tvb, offset, l);
6281                 coding = "JIS C 6226";
6282                 break;
6283             case ISO_10646_UCS4:
6284                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_UCS_4|ENC_BIG_ENDIAN);
6285                 coding = "ISO 10646 UCS-4";
6286                 break;
6287             case ISO_10646_UCS2:
6288                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_UCS_2|ENC_BIG_ENDIAN);
6289                 coding = "ISO 10646 UCS-2";
6290                 break;
6291             case ISO_8859_1:
6292                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_ISO_8859_1);
6293                 coding = "ISO 8859-1";
6294                 break;
6295             default:
6296                 /* Assume this is some form of extended ASCII, with one-byte code points for ASCII characters */
6297                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_ASCII);
6298                 coding = "unknown";
6299                 break;
6300             }
6301             ti = proto_tree_add_text(tree, tvb, offset, l, "%s%s '%s'", label, coding, out);
6302             lvt    -= l;
6303             offset += l;
6304         } while (lvt > 0);
6305
6306         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6307
6308         fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6309         proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, ENC_BIG_ENDIAN);
6310
6311         if (character_set == 1) {
6312             proto_tree_add_text(subtree, tvb, start+offs+1, 2, "Code Page: %d", tvb_get_ntohs(tvb, start+offs+1));
6313         }
6314         /* XXX - put the string value here */
6315     }
6316     return offset;
6317 }
6318
6319 static guint
6320 fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label,
6321     const value_string *src)
6322 {
6323     guint8      tag_no, tag_info, tmp;
6324     gint        j, unused, skip;
6325     guint       start = offset;
6326     guint       offs;
6327     guint32     lvt, i, numberOfBytes;
6328     guint8      bf_arr[256];
6329     proto_tree* subtree = tree;
6330     proto_item* ti;
6331
6332     offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6333     numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
6334     offset += offs;
6335     unused  = tvb_get_guint8(tvb, offset); /* get the unused Bits */
6336     ti      = proto_tree_add_text(tree, tvb, start, offs+lvt,
6337                                   "%s(Bit String)", label);
6338     if (ti) {
6339         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6340     }
6341     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6342     proto_tree_add_text(subtree, tvb, offset, 1,
6343                 "Unused bits: %u", unused);
6344     memset(bf_arr, 0, 256);
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 void
11025 proto_register_bacapp(void)
11026 {
11027     static hf_register_info hf[] = {
11028         { &hf_bacapp_type,
11029           { "APDU Type",           "bacapp.type",
11030             FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, NULL, HFILL }
11031         },
11032         { &hf_bacapp_pduflags,
11033           { "PDU Flags",          "bacapp.pduflags",
11034             FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }
11035         },
11036         { &hf_bacapp_SEG,
11037           { "Segmented Request",           "bacapp.segmented_request",
11038             FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, NULL, HFILL }
11039         },
11040         { &hf_bacapp_MOR,
11041           { "More Segments",           "bacapp.more_segments",
11042             FT_BOOLEAN, 8, TFS(&more_follow), 0x04, "More Segments Follow", HFILL }
11043         },
11044         { &hf_bacapp_SA,
11045           { "SA",           "bacapp.SA",
11046             FT_BOOLEAN, 8, TFS(&segmented_accept), 0x02, "Segmented Response accepted", HFILL }
11047         },
11048         { &hf_bacapp_max_adpu_size,
11049           { "Size of Maximum ADPU accepted",           "bacapp.max_adpu_size",
11050             FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, NULL, HFILL }
11051         },
11052         { &hf_bacapp_response_segments,
11053           { "Max Response Segments accepted",           "bacapp.response_segments",
11054             FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, NULL, HFILL }
11055         },
11056         { &hf_bacapp_objectType,
11057           { "Object Type",           "bacapp.objectType",
11058             FT_UINT32, BASE_DEC, VALS(BACnetObjectType), 0xffc00000, NULL, HFILL }
11059         },
11060         { &hf_bacapp_instanceNumber,
11061           { "Instance Number",           "bacapp.instance_number",
11062             FT_UINT32, BASE_DEC, NULL, 0x003fffff, NULL, HFILL }
11063         },
11064         { &hf_BACnetPropertyIdentifier,
11065           { "Property Identifier", "bacapp.property_identifier",
11066             FT_UINT32, BASE_DEC, VALS(BACnetPropertyIdentifier), 0, NULL, HFILL }
11067         },
11068         { &hf_BACnetVendorIdentifier,
11069           { "Vendor Identifier", "bacapp.vendor_identifier",
11070             FT_UINT16, BASE_DEC|BASE_EXT_STRING, &BACnetVendorIdentifiers_ext, 0, NULL, HFILL }
11071         },
11072         { &hf_BACnetRestartReason,
11073           { "Restart Reason", "bacapp.restart_reason",
11074             FT_UINT8, BASE_DEC, VALS(BACnetRestartReason), 0, NULL, HFILL }
11075         },
11076         { &hf_bacapp_invoke_id,
11077           { "Invoke ID",           "bacapp.invoke_id",
11078             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11079         },
11080         { &hf_bacapp_sequence_number,
11081           { "Sequence Number",           "bacapp.sequence_number",
11082             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11083         },
11084         { &hf_bacapp_window_size,
11085           { "Proposed Window Size",           "bacapp.window_size",
11086             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11087         },
11088         { &hf_bacapp_service,
11089           { "Service Choice",           "bacapp.confirmed_service",
11090             FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, NULL, HFILL }
11091         },
11092         { &hf_bacapp_uservice,
11093           { "Unconfirmed Service Choice",           "bacapp.unconfirmed_service",
11094             FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, NULL, HFILL }
11095         },
11096         { &hf_bacapp_NAK,
11097           { "NAK",           "bacapp.NAK",
11098             FT_BOOLEAN, 8, NULL, 0x02, "negative ACK", HFILL }
11099         },
11100         { &hf_bacapp_SRV,
11101           { "SRV",           "bacapp.SRV",
11102             FT_BOOLEAN, 8, NULL, 0x01, "Server", HFILL }
11103         },
11104         { &hf_Device_Instance_Range_Low_Limit,
11105           { "Device Instance Range Low Limit", "bacapp.who_is.low_limit",
11106             FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
11107         },
11108         { &hf_Device_Instance_Range_High_Limit,
11109           { "Device Instance Range High Limit", "bacapp.who_is.high_limit",
11110             FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
11111         },
11112         { &hf_BACnetRejectReason,
11113           { "Reject Reason",           "bacapp.reject_reason",
11114             FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, NULL, HFILL }
11115         },
11116         { &hf_BACnetAbortReason,
11117           { "Abort Reason",           "bacapp.abort_reason",
11118             FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, NULL, HFILL }
11119         },
11120         { &hf_BACnetApplicationTagNumber,
11121           { "Application Tag Number",
11122             "bacapp.application_tag_number",
11123             FT_UINT8, BASE_DEC, VALS(BACnetApplicationTagNumber), 0xF0,
11124             NULL, HFILL }
11125         },
11126         { &hf_BACnetContextTagNumber,
11127           { "Context Tag Number",
11128             "bacapp.context_tag_number",
11129             FT_UINT8, BASE_DEC, NULL, 0xF0,
11130             NULL, HFILL }
11131         },
11132         { &hf_BACnetExtendedTagNumber,
11133           { "Extended Tag Number",
11134             "bacapp.extended_tag_number",
11135             FT_UINT8, BASE_DEC, NULL, 0,
11136             NULL, HFILL }
11137         },
11138         { &hf_BACnetNamedTag,
11139           { "Named Tag",
11140             "bacapp.named_tag",
11141             FT_UINT8, BASE_DEC, VALS(BACnetTagNames), 0x07,
11142             NULL, HFILL }
11143         },
11144         { &hf_BACnetCharacterSet,
11145           { "String Character Set",
11146             "bacapp.string_character_set",
11147             FT_UINT8, BASE_DEC, VALS(BACnetCharacterSet), 0,
11148             NULL, HFILL }
11149         },
11150         { &hf_BACnetTagClass,
11151           { "Tag Class",           "bacapp.tag_class",
11152             FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, NULL, HFILL }
11153         },
11154         { &hf_bacapp_tag_lvt,
11155           { "Length Value Type",
11156             "bacapp.LVT",
11157             FT_UINT8, BASE_DEC, NULL, 0,
11158             NULL, HFILL }
11159         },
11160         { &hf_bacapp_tag_ProcessId,
11161           { "ProcessIdentifier",           "bacapp.processId",
11162             FT_UINT32, BASE_DEC, NULL, 0, "Process Identifier", HFILL }
11163         },
11164         { &hf_bacapp_tag_IPV4,
11165           { "IPV4",           "bacapp.IPV4",
11166             FT_IPv4, BASE_NONE, NULL, 0, "IP-Address", HFILL }
11167         },
11168         { &hf_bacapp_tag_IPV6,
11169           { "IPV6",           "bacapp.IPV6",
11170             FT_IPv6, BASE_NONE, NULL, 0, "IP-Address", HFILL }
11171         },
11172         { &hf_bacapp_tag_PORT,
11173           { "Port",           "bacapp.Port",
11174             FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
11175         },
11176         {&hf_msg_fragments,
11177          {"Message fragments", "bacapp.fragments",
11178           FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11179         {&hf_msg_fragment,
11180          {"Message fragment", "bacapp.fragment",
11181           FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11182         {&hf_msg_fragment_overlap,
11183          {"Message fragment overlap", "bacapp.fragment.overlap",
11184           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11185         {&hf_msg_fragment_overlap_conflicts,
11186          {"Message fragment overlapping with conflicting data",
11187           "bacapp.fragment.overlap.conflicts",
11188           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11189         {&hf_msg_fragment_multiple_tails,
11190          {"Message has multiple tail fragments",
11191           "bacapp.fragment.multiple_tails",
11192           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11193         {&hf_msg_fragment_too_long_fragment,
11194          {"Message fragment too long", "bacapp.fragment.too_long_fragment",
11195           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11196         {&hf_msg_fragment_error,
11197          {"Message defragmentation error", "bacapp.fragment.error",
11198           FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11199         {&hf_msg_fragment_count,
11200          {"Message fragment count", "bacapp.fragment.count",
11201           FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
11202         {&hf_msg_reassembled_in,
11203          {"Reassembled in", "bacapp.reassembled.in",
11204           FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11205         {&hf_msg_reassembled_length,
11206          {"Reassembled BACapp length", "bacapp.reassembled.length",
11207           FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }
11208     };
11209     static gint *ett[] = {
11210         &ett_bacapp,
11211         &ett_bacapp_control,
11212         &ett_bacapp_tag,
11213         &ett_bacapp_list,
11214         &ett_bacapp_value,
11215         &ett_msg_fragment,
11216         &ett_msg_fragments
11217
11218     };
11219
11220     static ei_register_info ei[] = {
11221         { &ei_bacapp_bad_length, { "bacapp.bad_length", PI_MALFORMED, PI_ERROR, "Wrong length indicated", EXPFILL }},
11222     };
11223
11224     expert_module_t* expert_bacapp;
11225
11226     proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
11227                                            "BACapp", "bacapp");
11228
11229     proto_register_field_array(proto_bacapp, hf, array_length(hf));
11230     proto_register_subtree_array(ett, array_length(ett));
11231     expert_bacapp = expert_register_protocol(proto_bacapp);
11232     expert_register_field_array(expert_bacapp, ei, array_length(ei));
11233     register_dissector("bacapp", dissect_bacapp, proto_bacapp);
11234     register_init_routine(&bacapp_init_routine);
11235
11236     bacapp_dissector_table = register_dissector_table("bacapp.vendor_identifier",
11237                                                       "BACapp Vendor Identifier",
11238                                                       FT_UINT8, BASE_HEX);
11239
11240     /* Register BACnet Statistic trees */
11241     register_bacapp_stat_trees();
11242     bacapp_tap = register_tap("bacapp"); /* BACnet statistics tap */
11243 }
11244
11245 /*
11246  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
11247  *
11248  * Local variables:
11249  * c-basic-offset: 4
11250  * tab-width: 8
11251  * indent-tabs-mode: nil
11252  * End:
11253  *
11254  * vi: set shiftwidth=4 tabstop=8 expandtab:
11255  * :indentSize=4:tabSize=8:noTabs=true:
11256  */