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