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