Replcae deprecated API tvb_length with tvb_reported_length or tvb_captured
[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  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald[AT]wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
27
28 #include "config.h"
29
30 #include <epan/packet.h>
31 #include <epan/to_str.h>
32 #include <epan/reassemble.h>
33 #include <epan/expert.h>
34 #include <epan/stats_tree.h>
35 #include "packet-bacapp.h"
36
37 static int bacapp_tap = -1;
38
39 /* formerly bacapp.h  contains definitions and forward declarations */
40
41 #ifndef FAULT
42 #define FAULT           proto_tree_add_text(subtree, tvb, offset, tvb_reported_length(tvb) - offset, "something is going wrong here !!"); \
43     offset = tvb_reported_length(tvb);
44 #endif
45
46 /* BACnet PDU Types */
47 #define BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST                   0
48 #define BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST                 1
49 #define BACAPP_TYPE_SIMPLE_ACK                                  2
50 #define BACAPP_TYPE_COMPLEX_ACK                                 3
51 #define BACAPP_TYPE_SEGMENT_ACK                                 4
52 #define BACAPP_TYPE_ERROR                                       5
53 #define BACAPP_TYPE_REJECT                                      6
54 #define BACAPP_TYPE_ABORT                                       7
55 #define MAX_BACAPP_TYPE                                         8
56
57 #define BACAPP_SEGMENTED_REQUEST 0x08
58 #define BACAPP_MORE_SEGMENTS 0x04
59 #define BACAPP_SEGMENTED_RESPONSE 0x02
60 #define BACAPP_SEGMENT_NAK 0x02
61 #define BACAPP_SENT_BY 0x01
62
63
64 /**
65  * dissect_bacapp ::= CHOICE {
66  *  confirmed-request-PDU       [0] BACnet-Confirmed-Request-PDU,
67  *  unconfirmed-request-PDU     [1] BACnet-Unconfirmed-Request-PDU,
68  *  simpleACK-PDU               [2] BACnet-SimpleACK-PDU,
69  *  complexACK-PDU              [3] BACnet-ComplexACK-PDU,
70  *  segmentACK-PDU              [4] BACnet-SegmentACK-PDU,
71  *  error-PDU                   [5] BACnet-Error-PDU,
72  *  reject-PDU                  [6] BACnet-Reject-PDU,
73  *  abort-PDU                   [7] BACnet-Abort-PDU
74  * }
75  * @param tvb the tv buffer of the current data
76  * @param pinfo the packet info of the current data
77  * @param tree the tree to append this item to
78  **/
79 static void
80 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
81
82 /**
83  * ConfirmedRequest-PDU ::= SEQUENCE {
84  *  pdu-type                    [0] Unsigned (0..15), -- 0 for this PDU Type
85  *  segmentedMessage            [1] BOOLEAN,
86  *  moreFollows                 [2] BOOLEAN,
87  *  segmented-response-accepted [3] BOOLEAN,
88  *  reserved                    [4] Unsigned (0..3), -- must be set zero
89  *  max-segments-accepted       [5] Unsigned (0..7), -- as per 20.1.2.4
90  *  max-APDU-length-accepted    [5] Unsigned (0..15), -- as per 20.1.2.5
91  *  invokeID                    [6] Unsigned (0..255),
92  *  sequence-number             [7] Unsigned (0..255) OPTIONAL, -- only if segmented msg
93  *  proposed-window-size        [8] Unsigned (0..127) OPTIONAL, -- only if segmented msg
94  *  service-choice              [9] BACnetConfirmedServiceChoice,
95  *  service-request             [10] BACnet-Confirmed-Service-Request OPTIONAL
96  * }
97  * @param tvb the tv buffer of the current data
98  * @param pinfo the packet info of the current data
99  * @param tree the tree to append this item to
100  * @param offset the offset in the tvb
101  * @return modified offset
102  */
103 static guint
104 fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
105
106 /**
107  * @param tvb the tv buffer of the current data
108  * @param pinfo the packet info of the current data
109  * @param tree the tree to append this item to
110  * @param offset the offset in the tvb
111  * @param ack - indocates whether working on request or ack
112  * @param svc - output variable to return service choice
113  * @param tt  - output varable to return service choice item
114  * @return modified offset
115  */
116 static guint
117 fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 ack,
118                 gint *svc, proto_item **tt);
119
120 /**
121  * Unconfirmed-Request-PDU ::= SEQUENCE {
122  *  pdu-type        [0] Unsigned (0..15), -- 1 for this PDU type
123  *  reserved        [1] Unsigned (0..15), -- must be set zero
124  *  service-choice  [2] BACnetUnconfirmedServiceChoice,
125  *  service-request [3] BACnetUnconfirmedServiceRequest -- Context-specific tags 0..3 are NOT used in header encoding
126  * }
127  * @param tvb the tv buffer of the current data
128  * @param pinfo the packet info of the current data
129  * @param tree the tree to append this item to
130  * @param offset the offset in the tvb
131  * @return modified offset
132  */
133 static guint
134 fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
135
136 /**
137  * SimpleACK-PDU ::= SEQUENCE {
138  *  pdu-type            [0] Unsigned (0..15), -- 2 for this PDU type
139  *  reserved            [1] Unsigned (0..15), -- must be set zero
140  *  invokeID            [2] Unsigned (0..255),
141  *  service-ACK-choice  [3] BACnetUnconfirmedServiceChoice -- Context-specific tags 0..3 are NOT used in header encoding
142  * }
143  * @param tvb the tv buffer of the current data
144  * @param pinfo the packet info of the current data
145  * @param tree the tree to append this item to
146  * @param offset the offset in the tvb
147  * @return modified offset
148  */
149 static guint
150 fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
151
152 /**
153  * ComplexACK-PDU ::= SEQUENCE {
154  *  pdu-type                [0] Unsigned (0..15), -- 3 for this PDU Type
155  *  segmentedMessage        [1] BOOLEAN,
156  *  moreFollows             [2] BOOLEAN,
157  *  reserved                [3] Unsigned (0..3), -- must be set zero
158  *  invokeID                [4] Unsigned (0..255),
159  *  sequence-number         [5] Unsigned (0..255) OPTIONAL, -- only if segmented msg
160  *  proposed-window-size    [6] Unsigned (0..127) OPTIONAL, -- only if segmented msg
161  *  service-ACK-choice      [7] BACnetConfirmedServiceChoice,
162  *  service-ACK             [8] BACnet-Confirmed-Service-Request  -- Context-specific tags 0..8 are NOT used in header encoding
163  * }
164  * @param tvb the tv buffer of the current data
165  * @param pinfo the packet info of the current data
166  * @param tree the tree to append this item to
167  * @param offset the offset in the tvb
168  * @return modified offset
169  */
170 static guint
171 fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
172
173 /**
174  * SegmentACK-PDU ::= SEQUENCE {
175  *  pdu-type                [0] Unsigned (0..15), -- 4 for this PDU Type
176  *  reserved                [1] Unsigned (0..3), -- must be set zero
177  *  negative-ACK            [2] BOOLEAN,
178  *  server                  [3] BOOLEAN,
179  *  original-invokeID       [4] Unsigned (0..255),
180  *  sequence-number         [5] Unsigned (0..255),
181  *  actual-window-size      [6] Unsigned (0..127)
182  * }
183  * @param tvb the tv buffer of the current data
184  * @param pinfo the packet info of the current data
185  * @param tree the tree to append this item to
186  * @param offset the offset in the tvb
187  * @return modified offset
188  */
189 static guint
190 fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
191
192 /**
193  * Error-PDU ::= SEQUENCE {
194  *  pdu-type                [0] Unsigned (0..15), -- 5 for this PDU Type
195  *  reserved                [1] Unsigned (0..3), -- must be set zero
196  *  original-invokeID       [2] Unsigned (0..255),
197  *  error-choice            [3] BACnetConfirmedServiceChoice,
198  *  error                   [4] BACnet-Error
199  * }
200  * @param tvb the tv buffer of the current data
201  * @param pinfo the packet info of the current data
202  * @param tree the tree to append this item to
203  * @param offset the offset in the tvb
204  * @return modified offset
205  */
206 static guint
207 fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
208
209 /**
210  * Reject-PDU ::= SEQUENCE {
211  *  pdu-type                [0] Unsigned (0..15), -- 6 for this PDU Type
212  *  reserved                [1] Unsigned (0..3), -- must be set zero
213  *  original-invokeID       [2] Unsigned (0..255),
214  *  reject-reason           [3] BACnetRejectReason
215  * }
216  * @param tvb the tv buffer of the current data
217  * @param pinfo the packet info of the current data
218  * @param tree the tree to append this item to
219  * @param offset the offset in the tvb
220  * @return modified offset
221  */
222 static guint
223 fRejectPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
224
225 /**
226  * Abort-PDU ::= SEQUENCE {
227  *  pdu-type                [0] Unsigned (0..15), -- 7 for this PDU Type
228  *  reserved                [1] Unsigned (0..3), -- must be set zero
229  *  server                  [2] BOOLEAN,
230  *  original-invokeID       [3] Unsigned (0..255),
231  *  abort-reason            [4] BACnetAbortReason
232  * }
233  * @param tvb the tv buffer of the current data
234  * @param pinfo the packet info of the current data
235  * @param tree the tree to append this item to
236  * @param offset the offset in the tvb
237  * @return modified offset
238  */
239 static guint
240 fAbortPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
241
242 /**
243  * 20.2.4, adds the label with max 64Bit unsigned Integer Value to tree
244  * @param tvb the tv buffer of the current data
245  * @param pinfo the packet info of the current data
246  * @param tree the tree to append this item to
247  * @param offset the offset in the tvb
248  * @param label the label of this item
249  * @return modified offset
250  */
251 static guint
252 fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
253
254 /**
255  * 20.2.5, adds the label with max 64Bit signed Integer Value to tree
256  * @param tvb the tv buffer of the current data
257  * @param pinfo the packet info of the current data
258  * @param tree the tree to append this item to
259  * @param offset the offset in the tvb
260  * @param label the label of this item
261  * @return modified offset
262  */
263 static guint
264 fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
265
266 /**
267  * 20.2.8, adds the label with Octet String to tree; if lvt == 0 then lvt = restOfFrame
268  * @param tvb the tv buffer of the current data
269  * @param pinfo the packet info of the current data
270  * @param tree the tree to append this item to
271  * @param offset the offset in the tvb
272  * @param label the label of this item
273  * @param lvt length of String
274  * @return modified offset
275  */
276 static guint
277 fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt);
278
279 /**
280  * 20.2.12, adds the label with Date Value to tree
281  * @param tvb the tv buffer of the current data
282  * @param pinfo the packet info of the current data
283  * @param tree the tree to append this item to
284  * @param offset the offset in the tvb
285  * @param label the label of this item
286  * @return modified offset
287  */
288 static guint
289 fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
290
291 /**
292  * 20.2.13, adds the label with Time Value to tree
293  * @param tvb the tv buffer of the current data
294  * @param pinfo the packet info of the current data
295  * @param tree the tree to append this item to
296  * @param offset the offset in the tvb
297  * @param label the label of this item
298  * @return modified offset
299  */
300 static guint
301 fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
302
303 /**
304  * 20.2.14, adds Object Identifier to tree
305  * use BIG ENDIAN: Bits 31..22 Object Type, Bits 21..0 Instance Number
306  * @param tvb the tv buffer of the current data
307  * @param pinfo the packet info of the current data
308  * @param tree the tree to append this item to
309  * @param offset the offset in the tvb
310  * @return modified offset
311  */
312 static guint
313 fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
314
315 /**
316  * BACnet-Confirmed-Service-Request ::= CHOICE {
317  * }
318  * @param tvb the tv buffer of the current data
319  * @param pinfo the packet info of the current data
320  * @param tree the tree to append this item to
321  * @param offset the offset in the tvb
322  * @param service_choice the service choice
323  * @return offset
324  */
325 static guint
326 fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
327
328 /**
329  * BACnet-Confirmed-Service-ACK ::= CHOICE {
330  * }
331  * @param tvb the tv buffer of the current data
332  * @param pinfo the packet info of the current data
333  * @param tree the tree to append this item to
334  * @param offset the offset in the tvb
335  * @param service_choice the service choice
336  * @return offset
337  */
338 static guint
339 fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
340
341 /**
342  * AcknowledgeAlarm-Request ::= SEQUENCE {
343  *  acknowledgingProcessIdentifier [0] Unsigned32,
344  *  eventObjectIdentifier          [1] BACnetObjectIdentifer,
345  *  eventStateAcknowledge          [2] BACnetEventState,
346  *  timeStamp                      [3] BACnetTimeStamp,
347  *  acknowledgementSource          [4] Character String,
348  *  timeOfAcknowledgement          [5] BACnetTimeStamp
349  * }
350  * @param tvb the tv buffer of the current data
351  * @param pinfo the packet info of the current data
352  * @param tree the tree to append this item to
353  * @param offset the offset in the tvb
354  * @return modified offset
355  */
356 static guint
357 fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
358
359 /**
360  * ConfirmedCOVNotification-Request ::= SEQUENCE {
361  *  subscriberProcessIdentifier [0] Unsigned32,
362  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
363  *  monitoredObjectIdentifier   [2] BACnetObjectIdentifer,
364  *  timeRemaining               [3] unsigned,
365  *  listOfValues                [4] SEQUENCE OF BACnetPropertyValues
366  * }
367  * @param tvb the tv buffer of the current data
368  * @param pinfo the packet info of the current data
369  * @param tree the tree to append this item to
370  * @param offset the offset in the tvb
371  * @return modified offset
372  */
373 static guint
374 fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
375
376 /**
377  * ConfirmedEventNotification-Request ::= SEQUENCE {
378  *  ProcessIdentifier           [0] Unsigned32,
379  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
380  *  eventObjectIdentifier       [2] BACnetObjectIdentifer,
381  *  timeStamp                   [3] BACnetTimeStamp,
382  *  notificationClass           [4] unsigned,
383  *  priority                    [5] unsigned8,
384  *  eventType                   [6] BACnetEventType,
385  *  messageText                 [7] CharacterString OPTIONAL,
386  *  notifyType                  [8] BACnetNotifyType,
387  *  ackRequired                 [9] BOOLEAN OPTIONAL,
388  *  fromState                  [10] BACnetEventState OPTIONAL,
389  *  toState                    [11] BACnetEventState,
390  *  eventValues                [12] BACnetNotificationParameters OPTIONAL
391  * }
392  * @param tvb the tv buffer of the current data
393  * @param pinfo the packet info of the current data
394  * @param tree the tree to append this item to
395  * @param offset the offset in the tvb
396  * @return modified offset
397  */
398 static guint
399 fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo,  proto_tree *tree, guint offset);
400
401 /**
402  * GetAlarmSummary-ACK ::= SEQUENCE OF SEQUENCE {
403  *  objectIdentifier         BACnetObjectIdentifer,
404  *  alarmState               BACnetEventState,
405  *  acknowledgedTransitions  BACnetEventTransitionBits
406  * }
407  * @param tvb the tv buffer of the current data
408  * @param pinfo the packet info of the current data
409  * @param tree the tree to append this item to
410  * @param offset the offset in the tvb
411  * @return modified offset
412  */
413 static guint
414 fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
415
416 /**
417  * GetEnrollmentSummary-Request ::= SEQUENCE {
418  *  acknowledgmentFilter    [0] ENUMERATED {
419  *      all       (0),
420  *      acked     (1),
421  *      not-acked (2)
422  *      },
423  *  enrollmentFilter        [1] BACnetRecipientProcess OPTIONAL,
424  *  eventStateFilter        [2] ENUMERATED {
425  *      offnormal (0),
426  *      fault     (1),
427  *      normal    (2),
428  *      all       (3),
429  *      active    (4)
430  *      },
431  *  eventTypeFilter         [3] BACnetEventType OPTIONAL,
432  *  priorityFilter          [4] SEQUENCE {
433  *      minPriority [0] Unsigned8,
434  *      maxPriority [1] Unsigned8
435  *      } OPTIONAL,
436  *  notificationClassFilter [5] Unsigned OPTIONAL
437  * }
438  * @param tvb the tv buffer of the current data
439  * @param pinfo the packet info of the current data
440  * @param tree the tree to append this item to
441  * @param offset the offset in the tvb
442  * @return modified offset
443  */
444 static guint
445 fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
446
447 /**
448  * GetEnrollmentSummary-ACK ::= SEQUENCE OF SEQUENCE {
449  *  objectIdentifier    BACnetObjectIdentifer,
450  *  eventType           BACnetEventType,
451  *  eventState          BACnetEventState,
452  *  priority            Unsigned8,
453  *  notificationClass   Unsigned OPTIONAL
454  * }
455  * @param tvb the tv buffer of the current data
456  * @param pinfo the packet info of the current data
457  * @param tree the tree to append this item to
458  * @param offset the offset in the tvb
459  * @return modified offset
460  */
461 static guint
462 fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
463
464 /**
465  * GetEventInformation-Request ::= SEQUENCE {
466  *  lastReceivedObjectIdentifier    [0] BACnetObjectIdentifer
467  * }
468  * @param tvb the tv buffer of the current data
469  * @param pinfo the packet info of the current data
470  * @param tree the tree to append this item to
471  * @param offset the offset in the tvb
472  * @return modified offset
473  */
474 static guint
475 fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
476
477 /**
478  * GetEventInformation-ACK ::= SEQUENCE {
479  *  listOfEventSummaries [0] listOfEventSummaries,
480  *  moreEvents           [1] BOOLEAN
481  * }
482  * @param tvb the tv buffer of the current data
483  * @param pinfo the packet info of the current data
484  * @param tree the tree to append this item to
485  * @param offset the offset in the tvb
486  * @return modified offset
487  */
488 static guint
489 fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
490
491 /**
492  * LifeSafetyOperation-Request ::= SEQUENCE {
493  *  requestingProcessIdentifier [0] Unsigned32
494  *  requestingSource            [1] CharacterString
495  *  request                     [2] BACnetLifeSafetyOperation
496  *  objectIdentifier            [3] BACnetObjectIdentifier OPTIONAL
497  * }
498  * @param tvb the tv buffer of the current data
499  * @param pinfo the packet info of the current data
500  * @param tree the tree to append this item to
501  * @param offset the offset in the tvb
502  * @return modified offset
503  */
504 static guint
505 fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
506
507 /**
508  * SubscribeCOV-Request ::= SEQUENCE {
509  *  subscriberProcessIdentifier [0] Unsigned32
510  *  monitoredObjectIdentifier   [1] BACnetObjectIdentifier
511  *  issueConfirmedNotifications [2] BOOLEAN OPTIONAL
512  *  lifetime                    [3] Unsigned OPTIONAL
513  * }
514  * @param tvb the tv buffer of the current data
515  * @param pinfo the packet info of the current data
516  * @param tree the tree to append this item to
517  * @param offset the offset in the tvb
518  * @return modified offset
519  */
520 static guint
521 fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
522
523 /**
524  * SubscribeCOVProperty-Request ::= SEQUENCE {
525  *  subscriberProcessIdentifier [0] Unsigned32
526  *  monitoredObjectIdentifier   [1] BACnetObjectIdentifier
527  *  issueConfirmedNotifications [2] BOOLEAN OPTIONAL
528  *  lifetime                    [3] Unsigned OPTIONAL
529  *  monitoredPropertyIdentifier [4] BACnetPropertyReference OPTIONAL
530  *  covIncrement                [5] Unsigned OPTIONAL
531  * }
532  * @param tvb the tv buffer of the current data
533  * @param pinfo the packet info of the current data
534  * @param tree the tree to append this item to
535  * @param offset the offset in the tvb
536  * @return modified offset
537  */
538 static guint
539 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
540
541 /**
542  * AtomicReadFile-Request ::= SEQUENCE {
543  *  fileIdentifier  BACnetObjectIdentifier,
544  *  accessMethod    CHOICE {
545  *      streamAccess    [0] SEQUENCE {
546  *          fileStartPosition   INTEGER,
547  *          requestedOctetCount Unsigned
548  *          },
549  *      recordAccess    [1] SEQUENCE {
550  *          fileStartRecord      INTEGER,
551  *          requestedRecordCount Unsigned
552  *          }
553  *      }
554  * }
555  * @param tvb the tv buffer of the current data
556  * @param pinfo the packet info of the current data
557  * @param tree the tree to append this item to
558  * @param offset the offset in the tvb
559  * @return modified offset
560  */
561 static guint
562 fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
563
564 /**
565  * AtomicWriteFile-ACK ::= SEQUENCE {
566  *  endOfFile   BOOLEAN,
567  *  accessMethod    CHOICE {
568  *      streamAccess    [0] SEQUENCE {
569  *          fileStartPosition   INTEGER,
570  *          fileData            OCTET STRING
571  *          },
572  *      recordAccess    [1] SEQUENCE {
573  *          fileStartRecord     INTEGER,
574  *          returnedRecordCount Unsigned,
575  *          fileRecordData      SEQUENCE OF OCTET STRING
576  *          }
577  *      }
578  * }
579  * @param tvb the tv buffer of the current data
580  * @param pinfo the packet info of the current data
581  * @param tree the tree to append this item to
582  * @param offset the offset in the tvb
583  * @return modified offset
584  */
585 static guint
586 fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
587
588 /**
589  * AtomicWriteFile-Request ::= SEQUENCE {
590  *  fileIdentifier  BACnetObjectIdentifier,
591  *  accessMethod    CHOICE {
592  *      streamAccess    [0] SEQUENCE {
593  *          fileStartPosition  INTEGER,
594  *          fileData           OCTET STRING
595  *          },
596  *      recordAccess    [1] SEQUENCE {
597  *          fileStartRecord    INTEGER,
598  *          recordCount        Unsigned,
599  *          fileRecordData     SEQUENCE OF OCTET STRING
600  *          }
601  *      }
602  * }
603  * @param tvb the tv buffer of the current data
604  * @param pinfo the packet info of the current data
605  * @param tree the tree to append this item to
606  * @param offset the offset in the tvb
607  * @return modified offset
608  */
609 static guint
610 fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
611
612 /**
613  * AtomicWriteFile-ACK ::= SEQUENCE {
614  *      fileStartPosition [0] INTEGER,
615  *      fileStartRecord   [1] INTEGER,
616  * }
617  * @param tvb the tv buffer of the current data
618  * @param pinfo the packet info of the current data
619  * @param tree the tree to append this item to
620  * @param offset the offset in the tvb
621  * @return modified offset
622  */
623 static guint
624 fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
625
626 /**
627  * AddListElement-Request ::= SEQUENCE {
628  *  objectIdentifier   [0] BACnetObjectIdentifier,
629  *  propertyIdentifier [1] BACnetPropertyIdentifier,
630  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
631  *  listOfElements     [3] ABSTRACT-SYNTAX.&Type
632  * }
633  * @param tvb the tv buffer of the current data
634  * @param pinfo the packet info of the current data
635  * @param tree the tree to append this item to
636  * @param offset the offset in the tvb
637  * @return modified offset
638  */
639 static guint
640 fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
641
642 /**
643  * CreateObject-Request ::= SEQUENCE {
644  *  objectSpecifier     [0] ObjectSpecifier,
645  *  listOfInitialValues [1] SEQUENCE OF BACnetPropertyValue OPTIONAL
646  * }
647  * @param tvb the tv buffer of the current data
648  * @param pinfo the packet info of the current data
649  * @param subtree the sub tree to append this item to
650  * @param offset the offset in the tvb
651  * @return modified offset
652  */
653 static guint
654 fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
655
656 /**
657  * CreateObject-Request ::= BACnetObjectIdentifier
658  * @param tvb the tv buffer of the current data
659  * @param pinfo the packet info of the current data
660  * @param tree the tree to append this item to
661  * @param offset the offset in the tvb
662  * @return modified offset
663  */
664 static guint
665 fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
666
667 /**
668  * DeleteObject-Request ::= SEQUENCE {
669  *  ObjectIdentifier    BACnetObjectIdentifer
670  * }
671  * @param tvb the tv buffer of the current data
672  * @param pinfo the packet info of the current data
673  * @param tree the tree to append this item to
674  * @param offset the offset in the tvb
675  * @return modified offset
676  */
677 static guint
678 fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
679
680 /**
681  * ReadProperty-Request ::= SEQUENCE {
682  *  objectIdentifier    [0] BACnetObjectIdentifier,
683  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
684  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
685  * }
686  * @param tvb the tv buffer of the current data
687  * @param pinfo the packet info of the current data
688  * @param tree the tree to append this item to
689  * @param offset the offset in the tvb
690  * @return modified offset
691  */
692 static guint
693 fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
694
695 /**
696  * ReadProperty-ACK ::= SEQUENCE {
697  *  objectIdentifier   [0] BACnetObjectIdentifier,
698  *  propertyIdentifier [1] BACnetPropertyIdentifier,
699  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
700  *  propertyValue      [3] ABSTRACT-SYNTAX.&Type
701  * }
702  * @param tvb the tv buffer of the current data
703  * @param pinfo the packet info of the current data
704  * @param tree the tree to append this item to
705  * @param offset the offset in the tvb
706  * @return modified offset
707  */
708 static guint
709 fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
710
711 /**
712  * ReadPropertyConditional-Request ::= SEQUENCE {
713  *  objectSelectionCriteria  [0] objectSelectionCriteria,
714  *  listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference OPTIONAL
715  * }
716  * @param tvb the tv buffer of the current data
717  * @param pinfo the packet info of the current data
718  * @param subtree the  sub tree to append this item to
719  * @param offset the offset in the tvb
720  * @return modified offset
721  */
722 static guint
723 fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
724
725 /**
726  * ReadPropertyConditional-ACK ::= SEQUENCE {
727  *  listOfPReadAccessResults    SEQUENCE OF ReadAccessResult OPTIONAL
728  * }
729  * @param tvb the tv buffer of the current data
730  * @param pinfo the packet info of the current data
731  * @param tree the tree to append this item to
732  * @param offset the offset in the tvb
733  * @return modified offset
734  */
735 static guint
736 fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
737
738 /**
739  * ReadPropertyMultiple-Request ::= SEQUENCE {
740  *  listOfReadAccessSpecs   SEQUENCE OF ReadAccessSpecification
741  * }
742  * @param tvb the tv buffer of the current data
743  * @param pinfo the packet info of the current data
744  * @param subtree the sub tree to append this item to
745  * @param offset the offset in the tvb
746  * @return offset modified
747  */
748 static guint
749 fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
750
751 /**
752  * ReadPropertyMultiple-Ack ::= SEQUENCE {
753  *  listOfReadAccessResults SEQUENCE OF ReadAccessResult
754  * }
755  * @param tvb the tv buffer of the current data
756  * @param pinfo the packet info of the current data
757  * @param tree the tree to append this item to
758  * @param offset the offset in the tvb
759  * @return offset modified
760  */
761 static guint
762 fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
763
764 /**
765  * ReadRange-Request ::= SEQUENCE {
766  *  objectIdentifier    [0] BACnetObjectIdentifier,
767  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
768  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
769  *  range   CHOICE {
770  *      byPosition  [3] SEQUENCE {
771  *          referencedIndex Unsigned,
772  *          count INTEGER
773  *          },
774  *      byTime      [4] SEQUENCE {
775  *          referenceTime BACnetDateTime,
776  *          count INTEGER
777  *          },
778  *      timeRange   [5] SEQUENCE {
779  *          beginningTime BACnetDateTime,
780  *          endingTime BACnetDateTime
781  *          },
782  *      } OPTIONAL
783  * }
784  * @param tvb the tv buffer of the current data
785  * @param pinfo the packet info of the current data
786  * @param tree the tree to append this item to
787  * @param offset the offset in the tvb
788  * @return modified offset
789  */
790 static guint
791 fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
792
793 /**
794  * ReadRange-ACK ::= SEQUENCE {
795  *  objectIdentifier   [0] BACnetObjectIdentifier,
796  *  propertyIdentifier [1] BACnetPropertyIdentifier,
797  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
798  *  resultFlags        [3] BACnetResultFlags,
799  *  itemCount          [4] Unsigned,
800  *  itemData           [5] SEQUENCE OF ABSTRACT-SYNTAX.&Type
801  * }
802  * @param tvb the tv buffer of the current data
803  * @param pinfo the packet info of the current data
804  * @param tree the tree to append this item to
805  * @param offset the offset in the tvb
806  * @return modified offset
807  */
808 static guint
809 fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
810
811 /**
812  * RemoveListElement-Request ::= SEQUENCE {
813  *  objectIdentifier    [0] BACnetObjectIdentifier,
814  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
815  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
816  *  listOfElements  [3] ABSTRACT-SYNTAX.&Type
817  * }
818  * @param tvb the tv buffer of the current data
819  * @param pinfo the packet info of the current data
820  * @param tree the tree to append this item to
821  * @param offset the offset in the tvb
822  * @return modified offset
823  */
824 static guint
825 fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
826
827 /**
828  * WriteProperty-Request ::= SEQUENCE {
829  *  objectIdentifier   [0] BACnetObjectIdentifier,
830  *  propertyIdentifier [1] BACnetPropertyIdentifier,
831  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
832  *  propertyValue      [3] ABSTRACT-SYNTAX.&Type
833  *  priority           [4] Unsigned8 (1..16) OPTIONAL --used only when property is commandable
834  * }
835  * @param tvb the tv buffer of the current data
836  * @param pinfo the packet info of the current data
837  * @param tree the tree to append this item to
838  * @param offset the offset in the tvb
839  * @return modified offset
840  */
841 static guint
842 fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
843
844 /**
845  * WritePropertyMultiple-Request ::= SEQUENCE {
846  *  listOfWriteAccessSpecifications SEQUENCE OF WriteAccessSpecification
847  * }
848  * @param tvb the tv buffer of the current data
849  * @param pinfo the packet info of the current data
850  * @param tree the tree to append this item to
851  * @param offset the offset in the tvb
852  * @return modified offset
853  */
854 static guint
855 fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
856
857 /**
858  * DeviceCommunicationControl-Request ::= SEQUENCE {
859  *  timeDuration    [0] Unsigned16 OPTIONAL,
860  *  enable-disable  [1] ENUMERATED {
861  *      enable  (0),
862  *      disable (1)
863  *      },
864  *  password        [2] CharacterString (SIZE(1..20)) OPTIONAL
865  * }
866  * @param tvb the tv buffer of the current data
867  * @param pinfo the packet info of the current data
868  * @param tree the tree to append this item to
869  * @param offset the offset in the tvb
870  * @return modified offset
871  */
872 static guint
873 fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
874
875 /**
876  * ConfirmedPrivateTransfer-Request ::= SEQUENCE {
877  *  vendorID          [0] Unsigned,
878  *  serviceNumber     [1] Unsigned,
879  *  serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
880  * }
881  * @param tvb the tv buffer of the current data
882  * @param pinfo the packet info of the current data
883  * @param tree the tree to append this item to
884  * @param offset the offset in the tvb
885  * @return modified offset
886  */
887 static guint
888 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
889
890 /**
891  * ConfirmedPrivateTransfer-ACK ::= SEQUENCE {
892  *  vendorID      [0] Unsigned,
893  *  serviceNumber [1] Unsigned,
894  *  resultBlock   [2] ABSTRACT-SYNTAX.&Type OPTIONAL
895  * }
896  * @param tvb the tv buffer of the current data
897  * @param pinfo the packet info of the current data
898  * @param tree the tree to append this item to
899  * @param offset the offset in the tvb
900  * @return modified offset
901  */
902 static guint
903 fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
904
905 /**
906  * ConfirmedTextMessage-Request ::=  SEQUENCE {
907  *  textMessageSourceDevice [0] BACnetObjectIdentifier,
908  *  messageClass            [1] CHOICE {
909  *      numeric   [0] Unsigned,
910  *      character [1] CharacterString
911  *      } OPTIONAL,
912  *  messagePriority         [2] ENUMERATED {
913  *      normal (0),
914  *      urgent (1)
915  *      },
916  *  message [3] CharacterString
917  * }
918  * @param tvb the tv buffer of the current data
919  * @param pinfo the packet info of the current data
920  * @param tree the tree to append this item to
921  * @param offset the offset in the tvb
922  * @return modified offset
923  */
924 static guint
925 fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
926
927 /**
928  * ReinitializeDevice-Request ::= SEQUENCE {
929  *  reinitializedStateOfDevice  [0] ENUMERATED {
930  *      coldstart    (0),
931  *      warmstart    (1),
932  *      startbackup  (2),
933  *      endbackup    (3),
934  *      startrestore (4),
935  *      endrestore   (5),
936  *      abortrestor  (6)
937  *      },
938  *  password                    [1] CharacterString (SIZE(1..20)) OPTIONAL
939  * }
940  * @param tvb the tv buffer of the current data
941  * @param pinfo the packet info of the current data
942  * @param tree the tree to append this item to
943  * @param offset the offset in the tvb
944  * @return modified offset
945  */
946 static guint
947 fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
948
949 /**
950  * VTOpen-Request ::= SEQUENCE {
951  *  vtClass BACnetVTClass,
952  *  localVTSessionIdentifier    Unsigned8
953  * }
954  * @param tvb the tv buffer of the current data
955  * @param pinfo the packet info of the current data
956  * @param tree the tree to append this item to
957  * @param offset the offset in the tvb
958  * @return modified offset
959  */
960 static guint
961 fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
962
963 /**
964  * VTOpen-ACK ::= SEQUENCE {
965  *  remoteVTSessionIdentifier   Unsigned8
966  * }
967  * @param tvb the tv buffer of the current data
968  * @param pinfo the packet info of the current data
969  * @param tree the tree to append this item to
970  * @param offset the offset in the tvb
971  * @return modified offset
972  */
973 static guint
974 fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
975
976 /**
977  * VTClose-Request ::= SEQUENCE {
978  *  listOfRemoteVTSessionIdentifiers    SEQUENCE OF Unsigned8
979  * }
980  * @param tvb the tv buffer of the current data
981  * @param pinfo the packet info of the current data
982  * @param tree the tree to append this item to
983  * @param offset the offset in the tvb
984  * @return modified offset
985  */
986 static guint
987 fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
988
989 /**
990  * VTData-Request ::= SEQUENCE {
991  *  vtSessionIdentifier Unsigned8,
992  *  vtNewData           OCTET STRING,
993  *  vtDataFlag          Unsigned (0..1)
994  * }
995  * @param tvb the tv buffer of the current data
996  * @param pinfo the packet info of the current data
997  * @param tree the tree to append this item to
998  * @param offset the offset in the tvb
999  * @return modified offset
1000  */
1001 static guint
1002 fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1003
1004 /**
1005  * VTData-ACK ::= SEQUENCE {
1006  *  allNewDataAccepted  [0] BOOLEAN,
1007  *  acceptedOctetCount  [1] Unsigned OPTIONAL -- present only if allNewDataAccepted = FALSE
1008  * }
1009  * @param tvb the tv buffer of the current data
1010  * @param pinfo the packet info of the current data
1011  * @param tree the tree to append this item to
1012  * @param offset the offset in the tvb
1013  * @return modified offset
1014  */
1015 static guint
1016 fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1017
1018 /**
1019  * Authenticate-Request ::= SEQUENCE {
1020  *  pseudoRandomNumber     [0] Unsigned32,
1021  *  excpectedInvokeID      [1] Unsigned8 OPTIONAL,
1022  *  operatorName           [2] CharacterString OPTIONAL,
1023  *  operatorPassword       [3] CharacterString (SIZE(1..20)) OPTIONAL,
1024  *  startEncypheredSession [4] BOOLEAN OPTIONAL
1025  * }
1026  * @param tvb the tv buffer of the current data
1027  * @param pinfo the packet info of the current data
1028  * @param tree the tree to append this item to
1029  * @param offset the offset in the tvb
1030  * @return modified offset
1031  */
1032 static guint
1033 fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1034
1035 /**
1036  * Authenticate-ACK ::= SEQUENCE {
1037  *  modifiedRandomNumber    Unsigned32,
1038  * }
1039  * @param tvb the tv buffer of the current data
1040  * @param pinfo the packet info of the current data
1041  * @param tree the tree to append this item to
1042  * @param offset the offset in the tvb
1043  * @return modified offset
1044  */
1045 static guint
1046 fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1047
1048 /**
1049  * RequestKey-Request ::= SEQUENCE {
1050  *  requestingDeviceIdentifier BACnetObjectIdentifier,
1051  *  requestingDeviceAddress    BACnetAddress,
1052  *  remoteDeviceIdentifier     BACnetObjectIdentifier,
1053  *  remoteDeviceAddress        BACnetAddress
1054  * }
1055  * @param tvb the tv buffer of the current data
1056  * @param pinfo the packet info of the current data
1057  * @param tree the tree to append this item to
1058  * @param offset the offset in the tvb
1059  * @return modified offset
1060  */
1061 static guint
1062 fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1063
1064 /**
1065  * Unconfirmed-Service-Request ::= CHOICE {
1066  * }
1067  * @param tvb the tv buffer of the current data
1068  * @param pinfo the packet info of the current data
1069  * @param tree the tree to append this item to
1070  * @param offset the offset in the tvb
1071  * @param service_choice the service choice
1072  * @return modified offset
1073  */
1074 static guint
1075 fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
1076
1077 /**
1078  * UnconfirmedCOVNotification-Request ::= SEQUENCE {
1079  *  subscriberProcessIdentifier [0] Unsigned32,
1080  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
1081  *  monitoredObjectIdentifier   [2] BACnetObjectIdentifer,
1082  *  timeRemaining               [3] unsigned,
1083  *  listOfValues                [4] SEQUENCE OF BACnetPropertyValues
1084  * }
1085  * @param tvb the tv buffer of the current data
1086  * @param pinfo the packet info of the current data
1087  * @param tree the tree to append this item to
1088  * @param offset the offset in the tvb
1089  * @return modified offset
1090  */
1091 static guint
1092 fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1093
1094 /**
1095  * UnconfirmedEventNotification-Request ::= SEQUENCE {
1096  *  ProcessIdentifier           [0] Unsigned32,
1097  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
1098  *  eventObjectIdentifier       [2] BACnetObjectIdentifer,
1099  *  timeStamp                   [3] BACnetTimeStamp,
1100  *  notificationClass           [4] unsigned,
1101  *  priority                    [5] unsigned8,
1102  *  eventType                   [6] BACnetEventType,
1103  *  messageText                 [7] CharacterString OPTIONAL,
1104  *  notifyType                  [8] BACnetNotifyType,
1105  *  ackRequired                 [9] BOOLEAN OPTIONAL,
1106  *  fromState                  [10] BACnetEventState OPTIONAL,
1107  *  toState                    [11] BACnetEventState,
1108  *  eventValues                [12] BACnetNotificationParameters OPTIONAL
1109  * }
1110  * @param tvb the tv buffer of the current data
1111  * @param pinfo the packet info of the current data
1112  * @param tree the tree to append this item to
1113  * @param offset the offset in the tvb
1114  * @return modified offset
1115  */
1116 static guint
1117 fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1118
1119 /**
1120  * I-Am-Request ::= SEQUENCE {
1121  *  aAmDeviceIdentifier BACnetObjectIdentifier,
1122  *  maxAPDULengthAccepted   Unsigned,
1123  *  segmentationSupported   BACnetSegmentation,
1124  *  vendorID    Unsigned
1125  * }
1126  * @param tvb the tv buffer of the current data
1127  * @param pinfo the packet info of the current data
1128  * @param tree the tree to append this item to
1129  * @param offset the offset in the tvb
1130  * @return modified offset
1131  */
1132 static guint
1133 fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1134
1135
1136 /**
1137  * I-Have-Request ::= SEQUENCE {
1138  *  deviceIdentifier  BACnetObjectIdentifier,
1139  *  objectIdentifier  BACnetObjectIdentifier,
1140  *  objectName        CharacterString
1141  * }
1142  * @param tvb the tv buffer of the current data
1143  * @param pinfo the packet info of the current data
1144  * @param tree the tree to append this item to
1145  * @param offset the offset in the tvb
1146  * @return modified offset
1147  */
1148 static guint
1149 fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1150
1151 /**
1152  * UnconfirmedPrivateTransfer-Request ::= SEQUENCE {
1153  *  vendorID          [0] Unsigned,
1154  *  serviceNumber     [1] Unsigned,
1155  *  serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
1156  * }
1157  * @param tvb the tv buffer of the current data
1158  * @param pinfo the packet info of the current data
1159  * @param tree the tree to append this item to
1160  * @param offset the offset in the tvb
1161  * @return modified offset
1162  */
1163 static guint
1164 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1165
1166 /**
1167  * UnconfirmedTextMessage-Request ::=  SEQUENCE {
1168  *  textMessageSourceDevice [0] BACnetObjectIdentifier,
1169  *  messageClass            [1] CHOICE {
1170  *      numeric   [0] Unsigned,
1171  *      character [1] CharacterString
1172  *      } OPTIONAL,
1173  *  messagePriority         [2] ENUMERATED {
1174  *      normal (0),
1175  *      urgent (1)
1176  *      },
1177  *  message                 [3] CharacterString
1178  * }
1179  * @param tvb the tv buffer of the current data
1180  * @param pinfo the packet info of the current data
1181  * @param tree the tree to append this item to
1182  * @param offset the offset in the tvb
1183  * @return modified offset
1184  */
1185 static guint
1186 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1187
1188 /**
1189  * TimeSynchronization-Request ::=  SEQUENCE {
1190  *  BACnetDateTime
1191  * }
1192  * @param tvb the tv buffer of the current data
1193  * @param pinfo the packet info of the current data
1194  * @param tree the tree to append this item to
1195  * @param offset the offset in the tvb
1196  * @return modified offset
1197  */
1198 static guint
1199 fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1200
1201 /**
1202  * UTCTimeSynchronization-Request ::=  SEQUENCE {
1203  *  BACnetDateTime
1204  * }
1205  * @param tvb the tv buffer of the current data
1206  * @param pinfo the packet info of the current data
1207  * @param tree the tree to append this item to
1208  * @param offset the offset in the tvb
1209  * @return modified offset
1210  */
1211 static guint
1212 fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1213
1214 /**
1215  * Who-Has-Request ::=  SEQUENCE {
1216  *  limits SEQUENCE {
1217  *      deviceInstanceRangeLowLimit  [0] Unsigned (0..4194303),
1218  *      deviceInstanceRangeHighLimit [1] Unsigned (0..4194303)
1219  *      } OPTIONAL,
1220  *  object CHOICE {
1221  *      objectIdentifier             [2] BACnetObjectIdentifier,
1222  *      objectName                   [3] CharacterString
1223  *      }
1224  * }
1225  * @param tvb the tv buffer of the current data
1226  * @param pinfo the packet info of the current data
1227  * @param tree the tree to append this item to
1228  * @param offset the offset in the tvb
1229  * @return modified offset
1230  */
1231 static guint
1232 fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1233
1234 /**
1235  * Who-Is-Request ::= SEQUENCE {
1236  *  deviceInstanceRangeLowLimit  [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1237  *  deviceInstanceRangeHighLimit [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1238  * }
1239  * @param tvb the tv buffer of the current data
1240  * @param tree the tree to append this item to
1241  * @param offset the offset in the tvb
1242  * @return modified offset
1243  */
1244 static guint
1245 fWhoIsRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1246
1247 /**
1248  * BACnet-Error ::= CHOICE {
1249  *  addListElement           [8] ChangeList-Error,
1250  *  removeListElement        [9] ChangeList-Error,
1251  *  writePropertyMultiple   [16] WritePropertyMultiple-Error,
1252  *  confirmedPrivatTransfer [18] ConfirmedPrivateTransfer-Error,
1253  *  vtClose                 [22] VTClose-Error,
1254  *  readRange               [26] ObjectAccessService-Error
1255  *                          [default] Error
1256  * }
1257  * @param tvb the tv buffer of the current data
1258  * @param pinfo the packet info of the current data
1259  * @param tree the tree to append this item to
1260  * @param offset the offset in the tvb
1261  * @param service the service
1262  * @return modified offset
1263  */
1264 static guint
1265 fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service);
1266
1267 /**
1268  * Dissect a BACnetError in a context tag
1269  *
1270  * @param tvb the tv buffer of the current data
1271  * @param pinfo the packet info of the current data
1272  * @param tree the tree to append this item to
1273  * @param offset the offset in the tvb
1274  * @return modified offset
1275  */
1276 static guint fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1277
1278 /**
1279  * ChangeList-Error ::= SEQUENCE {
1280  *    errorType                [0] Error,
1281  *    firstFailedElementNumber [1] Unsigned
1282  *    }
1283  * }
1284  * @param tvb the tv buffer of the current data
1285  * @param pinfo the packet info of the current data
1286  * @param tree the tree to append this item to
1287  * @param offset the offset in the tvb
1288  * @return modified offset
1289  */
1290 static guint
1291 fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1292
1293 /**
1294  * CreateObject-Error ::= SEQUENCE {
1295  *    errorType                [0] Error,
1296  *    firstFailedElementNumber [1] Unsigned
1297  *    }
1298  * }
1299  * @param tvb the tv buffer of the current data
1300  * @param pinfo the packet info of the current data
1301  * @param tree the tree to append this item to
1302  * @param offset the offset in the tvb
1303  * @return modified offset
1304  */
1305 static guint
1306 fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1307
1308 /**
1309  * ConfirmedPrivateTransfer-Error ::= SEQUENCE {
1310  *    errorType       [0] Error,
1311  *    vendorID        [1] Unsigned,
1312  *    serviceNumber   [2] Unsigned,
1313  *    errorParameters [3] ABSTRACT-SYNTAX.&Type OPTIONAL
1314  *    }
1315  * }
1316  * @param tvb the tv buffer of the current data
1317  * @param pinfo the packet info of the current data
1318  * @param tree the tree to append this item to
1319  * @param offset the offset in the tvb
1320  * @return modified offset
1321  */
1322 static guint
1323 fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1324
1325 /**
1326  * WritePropertyMultiple-Error ::= SEQUENCE {
1327  *    errorType               [0] Error,
1328  *    firstFailedWriteAttempt [1] Unsigned
1329  *    }
1330  * }
1331  * @param tvb the tv buffer of the current data
1332  * @param pinfo the packet info of the current data
1333  * @param tree the tree to append this item to
1334  * @param offset the offset in the tvb
1335  * @return modified offset
1336  */
1337 static guint
1338 fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1339
1340 /**
1341  * VTClose-Error ::= SEQUENCE {
1342  *    errorType                  [0] Error,
1343  *    listOfVTSessionIdentifiers [1] SEQUENCE OF Unsigned8 OPTIONAL
1344  *    }
1345  * }
1346  * @param tvb the tv buffer of the current data
1347  * @param pinfo the packet info of the current data
1348  * @param tree the tree to append this item to
1349  * @param offset the offset in the tvb
1350  * @return modified offset
1351  */
1352 static guint
1353 fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1354
1355 /**
1356  * BACnet Application Types chapter 20.2.1
1357  * @param tvb the tv buffer of the current data
1358  * @param pinfo the packet info of the current data
1359  * @param tree the tree to append this item to
1360  * @param offset the offset in the tvb
1361  * @param label the label of this item
1362  * @return modified offset
1363  */
1364 static guint
1365 fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
1366
1367 /**
1368  * BACnetActionCommand ::= SEQUENCE {
1369  *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1370  *  objectIdentifier    [1] BACnetObjectIdentifier,
1371  *  propertyIdentifier  [2] BACnetPropertyIdentifier,
1372  *  propertyArrayIndex  [3] Unsigned OPTIONAL, -- used only with array datatype
1373  *  propertyValue       [4] ABSTRACT-SYNTAX.&Type,
1374  *  priority            [5] Unsigned (1..16) OPTIONAL, -- used only when property is commandable
1375  *  postDelay           [6] Unsigned OPTIONAL,
1376  *  quitOnFailure       [7] BOOLEAN,
1377  *  writeSuccessful     [8] BOOLEAN
1378  * }
1379  * @param tvb the tv buffer of the current data
1380  * @param pinfo the packet info of the current data
1381  * @param tree the tree to append this item to
1382  * @param offset the offset in the tvb
1383  * @param tag_match the tag number
1384  * @return modified offset
1385  */
1386 static guint
1387 fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match);
1388
1389 /**
1390  * BACnetActionList ::= SEQUENCE {
1391  *  action  [0] SEQUENCE of BACnetActionCommand
1392  * }
1393  * @param tvb the tv buffer of the current data
1394  * @param pinfo the packet info of the current data
1395  * @param tree the tree to append this item to
1396  * @param offset the offset in the tvb
1397  * @return modified offset
1398  */
1399 static guint
1400 fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1401
1402 /** BACnetAddress ::= SEQUENCE {
1403  *  network-number  Unsigned16, -- A value 0 indicates the local network
1404  *  mac-address     OCTET STRING -- A string of length 0 indicates a broadcast
1405  * }
1406  * @param tvb the tv buffer of the current data
1407  * @param pinfo the packet info of the current data
1408  * @param tree the tree to append this item to
1409  * @param offset the offset in the tvb
1410  * @return modified offset
1411  */
1412 static guint
1413 fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1414
1415 /**
1416  * BACnetAddressBinding ::= SEQUENCE {
1417  *  deviceObjectID  BACnetObjectIdentifier
1418  *  deviceAddress   BacnetAddress
1419  * }
1420  * @param tvb the tv buffer of the current data
1421  * @param pinfo the packet info of the current data
1422  * @param tree the tree to append this item to
1423  * @param offset the offset in the tvb
1424  * @return modified offset
1425  */
1426 static guint
1427 fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1428
1429 /**
1430  * BACnetCalendarEntry ::= CHOICE {
1431  *  date        [0] Date,
1432  *  dateRange   [1] BACnetDateRange,
1433  *  weekNDay    [2] BacnetWeekNday
1434  * }
1435  * @param tvb the tv buffer of the current data
1436  * @param pinfo the packet info of the current data
1437  * @param tree the tree to append this item to
1438  * @param offset the offset in the tvb
1439  * @return modified offset
1440  */
1441 static guint
1442 fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1443
1444 /**
1445  * BACnetClientCOV ::= CHOICE {
1446  *  real-increment  REAL,
1447  *  default-increment   NULL
1448  * }
1449  * @param tvb the tv buffer of the current data
1450  * @param tree the tree to append this item to
1451  * @param offset the offset in the tvb
1452  * @return modified offset
1453  */
1454 static guint
1455 fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1456
1457
1458 /**
1459  * BACnetDailySchedule ::= SEQUENCE {
1460  *  day-schedule    [0] SENQUENCE OF BACnetTimeValue
1461  * }
1462  * @param tvb the tv buffer of the current data
1463  * @param pinfo the packet info of the current data
1464  * @param tree the tree to append this item to
1465  * @param offset the offset in the tvb
1466  * @return modified offset
1467  */
1468 static guint
1469 fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1470
1471 /**
1472  * BACnetWeeklySchedule ::= SEQUENCE {
1473  *  week-schedule    SENQUENCE SIZE (7) OF BACnetDailySchedule
1474  * }
1475  * @param tvb the tv buffer of the current data
1476  * @param pinfo the packet info of the current data
1477  * @param tree the tree to append this item to
1478  * @param offset the offset in the tvb
1479  * @return modified offset
1480  */
1481 static guint
1482 fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1483
1484 /**
1485  * BACnetDateRange ::= SEQUENCE {
1486  *  StartDate   Date,
1487  *  EndDate     Date
1488  * }
1489  * @param tvb the tv buffer of the current data
1490  * @param pinfo the packet info of the current data
1491  * @param tree the tree to append this item to
1492  * @param offset the offset in the tvb
1493  * @return modified offset
1494  */
1495 static guint
1496 fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1497
1498 /**
1499  * BACnetDateTime ::= SEQUENCE {
1500  *  date   Date,
1501  *  time   Time
1502  * }
1503  * @param tvb the tv buffer of the current data
1504  * @param pinfo the packet info of the current data
1505  * @param tree the tree to append this item to
1506  * @param offset the offset in the tvb
1507  * @param label the label of this item
1508  * @return modified offset
1509  */
1510 static guint
1511 fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
1512
1513 /**
1514  * BACnetDestination ::= SEQUENCE {
1515  *  validDays   BACnetDaysOfWeek,
1516  *  fromTime    Time,
1517  *  toTime      Time,
1518  *  recipient   BACnetRecipient,
1519  *  processIdentifier   Unsigned32,
1520  *  issueConfirmedNotifications BOOLEAN,
1521  *  transitions BACnetEventTransitionBits
1522  * }
1523  * @param tvb the tv buffer of the current data
1524  * @param pinfo the packet info of the current data
1525  * @param tree the tree to append this item to
1526  * @param offset the offset in the tvb
1527  * @return modified offset
1528  */
1529 static guint
1530 fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1531
1532 /**
1533  * BACnetDeviceObjectPropertyReference ::= SEQUENCE {
1534  *  objectIdentifier    [0] BACnetObjectIdentifier,
1535  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1536  *  propertyArrayIndex  [2] Unsigend OPTIONAL,
1537  *  deviceIdentifier    [3] BACnetObjectIdentifier OPTIONAL
1538  * }
1539  * @param tvb the tv buffer of the current data
1540  * @param pinfo the packet info of the current data
1541  * @param tree the tree to append this item to
1542  * @param offset the offset in the tvb
1543  * @return modified offset
1544  */
1545 static guint
1546 fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1547
1548 /**
1549  * BACnetObjectPropertyReference ::= SEQUENCE {
1550  *  objectIdentifier    [0] BACnetObjectIdentifier,
1551  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1552  *  propertyArrayIndex  [2] Unsigend OPTIONAL,
1553  * }
1554  * @param tvb the tv buffer of the current data
1555  * @param pinfo the packet info of the current data
1556  * @param tree the tree to append this item to
1557  * @param offset the offset in the tvb
1558  * @return modified offset
1559  */
1560 static guint
1561 fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1562
1563 /**
1564  * BACnetDeviceObjectReference ::= SEQUENCE {
1565  *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1566  *  objectIdentifier    [1] BACnetObjectIdentifier
1567  * }
1568  * @param tvb the tv buffer of the current data
1569  * @param pinfo the packet info of the current data
1570  * @param tree the tree to append this item to
1571  * @param offset the offset in the tvb
1572  * @return modified offset
1573  */
1574 static guint
1575 fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1576
1577 /**
1578  * BACnetEventParameter ::= CHOICE {
1579  *  change-of-bitstring             [0] SEQUENCE {
1580  *      time-delay                       [0] Unsigned,
1581  *      bitmask                          [1] BIT STRING,
1582  *      list-of-bitstring-values         [2] SEQUENCE OF BIT STRING
1583  *      },
1584  *  change-of-state                 [1] SEQUENCE {
1585  *      time-delay     [0] Unsigned,
1586  *      list-of-values [1] SEQUENCE OF BACnetPropertyStates
1587  *      },
1588  *  change-of-value                 [2] SEQUENCE {
1589  *      time-delay   [0] Unsigned,
1590  *      cov-criteria [1] CHOICE {
1591  *          bitmask                       [0] BIT STRING,
1592  *          referenced-property-increment [1] REAL
1593  *          }
1594  *      },
1595  *  command-failure                 [3] SEQUENCE {
1596  *      time-delay                       [0] Unsigned,
1597  *      feedback-property-reference      [1] BACnetDeviceObjectPropertyReference
1598  *      },
1599  *  floating-limit                  [4] SEQUENCE {
1600  *      time-delay                       [0] Unsigned,
1601  *      setpoint-reference               [1] BACnetDeviceObjectPropertyReference,
1602  *      low-diff-limit                   [2] REAL,
1603  *      high-diff-limit                  [3] REAL,
1604  *      deadband                         [4] REAL
1605  *      },
1606  *  out-of-range                    [5] SEQUENCE {
1607  *      time-delay                       [0] Unsigned,
1608  *      low-limit                        [1] REAL,
1609  *      high-limit                       [2] REAL,
1610  *      deadband                         [3] REAL
1611  *      },
1612  *  -- context tag 7 is deprecated
1613  *  change-of-life-safety           [8] SEQUENCE {
1614  *      time-delay                       [0] Unsigned,
1615  *      list-of-life-safety-alarm-values [1] SEQUENCE OF BACnetLifeSafetyState,
1616  *      list-of-alarm-values             [2] SEQUENCE OF BACnetLifeSafetyState,
1617  *      mode-property-reference          [3] BACnetDeviceObjectPropertyReference
1618  *      },
1619  *  extended                        [9] SEQUENCE {
1620  *      vendor-id                        [0] Unsigned16,
1621  *      extended-event-type              [1] Unsigned,
1622  *      parameters                       [2] SEQUENCE OF CHOICE {
1623  *          null        NULL,
1624  *          real        REAL,
1625  *          integer     Unsigned,
1626  *          boolean     BOOLEAN,
1627  *          double      Double,
1628  *          octet       OCTET STRING,
1629  *          bitstring   BIT STRING,
1630  *          enum        ENUMERATED,
1631  *          reference   [0] BACnetDeviceObjectPropertyReference
1632  *          }
1633  *      },
1634  *  buffer-ready                    [10] SEQUENCE {
1635  *      notification-threshold           [0] Unsigned,
1636  *      previous-notification-count      [1] Unsigned32
1637  *      },
1638  * unsigned-range                   [11] SEQUENCE {
1639  *      time-delay                       [0] Unsigned,
1640  *      low-limit                        [1] Unsigned,
1641  *      high-limit                       [2] Unsigned,
1642  *      }
1643  * -- context tag 12 is reserved for future addenda
1644  * access-event                     [13] SEQUENCE {
1645  *      list-of-access-events            [0] SEQUENCE OF BACnetAccessEvent,
1646  *      access-event-time-reference      [1] BACnetDeviceObjectPropertyReference
1647  *      }
1648  * double-out-of-range              [14] SEQUENCE {
1649  *      time-delay                       [0] Unsigned,
1650  *      low-limit                        [1] Double,
1651  *      high-limit                       [2] Double,
1652  *      deadband                         [3] Double
1653  *  }
1654  *  signed-out-of-range             [15] SEQUENCE {
1655  *      time-delay                       [0] Unsigned,
1656  *      low-limit                        [1] INTEGER,
1657  *      high-limit                       [2] INTEGER,
1658  *      deadband                         [3] Unsigned
1659  *  }
1660  *  unsigned-out-of-range           [16] SEQUENCE {
1661  *      time-delay                       [0] Unsigned,
1662  *      low-limit                        [1] Unsigned,
1663  *      high-limit                       [2] Unsigned,
1664  *      deadband                         [3] Unsigned
1665  *   }
1666  *  change-of-characterstring       [17] SEQUENCE {
1667  *      time-delay                       [0] Unsigned,
1668  *      list-of-alarm-values             [1] SEQUENCE OF CharacterString,
1669  *   }
1670  *  change-of-status-flags          [18] SEQUENCE {
1671  *      time-delay                       [0] Unsigned,
1672  *      selected-flags                   [1] BACnetStatusFlags
1673  *   }
1674  * }
1675  * @param tvb the tv buffer of the current data
1676  * @param tree the tree to append this item to
1677  * @param offset the offset in the tvb
1678  * @return modified offset
1679  */
1680 static guint
1681 fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1682
1683
1684
1685 /**
1686  * BACnetLogRecord ::= SEQUENCE {
1687  *  timestamp   [0] BACnetDateTime,
1688  *  logDatum    [1] CHOICE {
1689  *      log-status      [0] BACnetLogStatus,
1690  *      boolean-value   [1] BOOLEAN,
1691  *      real-value      [2] REAL,
1692  *      enum-value      [3] ENUMERATED, -- Optionally limited to 32 bits
1693  *      unsigned-value  [4] Unsigned, -- Optionally limited to 32 bits
1694  *      signed-value    [5] INTEGER, -- Optionally limited to 32 bits
1695  *      bitstring-value [6] BIT STRING, -- Optionally limited to 32 bits
1696  *      null-value      [7] NULL,
1697  *      failure         [8] Error,
1698  *      time-change     [9] REAL,
1699  *      any-value       [10] ABSTRACT-SYNTAX.&Type -- Optional
1700  *      }
1701  *  statusFlags [2] BACnetStatusFlags OPTIONAL
1702  * }
1703  * @param tvb the tv buffer of the current data
1704  * @param pinfo the packet info of the current data
1705  * @param tree the tree to append this item to
1706  * @param offset the offset in the tvb
1707  * @return modified offset
1708  */
1709 static guint
1710 fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1711
1712 /**
1713  * BACnetEventLogRecord ::= SEQUENCE {
1714  *  timestamp [0] BACnetDateTime,
1715  *  logDatum  [1] CHOICE {
1716  *      log-status   [0] BACnetLogStatus,
1717  *      notification [1] ConfirmedEventNotification-Request,
1718  *      time-change  [2] REAL,
1719  *      }
1720  * }
1721  * @param tvb the tv buffer of the current data
1722  * @param pinfo the packet info of the current data
1723  * @param tree the tree to append this item to
1724  * @param offset the offset in the tvb
1725  * @return modified offset
1726  */
1727 static guint
1728 fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1729
1730 static guint
1731 fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1732
1733 /**
1734  * BACnetNotificationParameters ::= CHOICE {
1735  *  change-of-bitstring [0] SEQUENCE {
1736  *      referenced-bitstring [0] BIT STRING,
1737  *      status-flags         [1] BACnetStatusFlags
1738  *      },
1739  *  change-of-state [1] SEQUENCE {
1740  *      new-state            [0] BACnetPropertyStatus,
1741  *      status-flags         [1] BACnetStatusFlags
1742  *      },
1743  *  change-of-value [2] SEQUENCE {
1744  *      new-value            [0] CHOICE {
1745  *          changed-bits        [0] BIT STRING,
1746  *          changed-value       [1] REAL
1747  *          },
1748  *      status-flags         [1] BACnetStatusFlags
1749  *      },
1750  *  command-failure [3] SEQUENCE {
1751  *      command-value        [0] ABSTRACT-SYNTAX.&Type, -- depends on ref property
1752  *      status-flags         [1] BACnetStatusFlags
1753  *      feedback-value       [2] ABSTRACT-SYNTAX.&Type -- depends on ref property
1754  *      },
1755  *  floating-limit [4]  SEQUENCE {
1756  *      reference-value      [0] REAL,
1757  *      status-flags         [1] BACnetStatusFlags
1758  *      setpoint-value       [2] REAL,
1759  *      error-limit          [3] REAL
1760  *      },
1761  *  out-of-range [5]    SEQUENCE {
1762  *      exceeding-value      [0] REAL,
1763  *      status-flags         [1] BACnetStatusFlags
1764  *      deadband             [2] REAL,
1765  *      exceeded-limit       [3] REAL
1766  *      },
1767  *  complex-event-type  [6] SEQUENCE OF BACnetPropertyValue,
1768  * -- complex tag 7 is deprecated
1769  *  change-of-life-safety [8]   SEQUENCE {
1770  *      new-state            [0] BACnetLifeSafetyState,
1771  *      new-mode             [1] BACnetLifeSafetyState
1772  *      status-flags         [2] BACnetStatusFlags,
1773  *      operation-expected   [3] BACnetLifeSafetyOperation
1774  *      },
1775  *  extended [9]   SEQUENCE {
1776  *      vendor-id            [0] Unsigned16,
1777  *      extended-event-type  [1] Unsigned,
1778  *      parameters           [2] SEQUENCE OF CHOICE {
1779  *          null                NULL,
1780  *          real                REAL,
1781  *          integer             Unsigned,
1782  *          boolean             BOOLEAN,
1783  *          double              Double,
1784  *          octet               OCTET STRING,
1785  *          bitstring           BIT STRING,
1786  *          enum                ENUMERATED,
1787  *          propertyValue       [0] BACnetDeviceObjectPropertyValue
1788  *          }
1789  *      },
1790  *  buffer-ready [10]    SEQUENCE {
1791  *      buffer-property      [0] BACnetDeviceObjectPropertyReference,
1792  *      previous-notification[1] Unsigned32,
1793  *      current-notification [2] BACneUnsigned32tDateTime
1794  *      },
1795  *  unsigned-range [11]    SEQUENCE {
1796  *      exceeding-value      [0] Unsigned,
1797  *      status-flags         [1] BACnetStatusFlags,
1798  *      exceeded-limit       [2] Unsigned
1799  *      },
1800  * -- context tag 12 is reserved for future addenda
1801  *  access-event [13]    SEQUENCE {
1802  *      access-event          [0] BACnetAccessEvent,
1803  *      status-flags          [1] BACnetStatusFlags,
1804  *      access-event-tag      [2] Unsigned,
1805  *      access-event-time     [3] BACnetTimeStamp,
1806  *      access-credential     [4] BACnetDeviceObjectReference,
1807  *      authentication-factor [5] BACnetAuthenticationFactor OPTIONAL
1808  *      },
1809  *  double-out-of-range [14]    SEQUENCE {
1810  *      exceeding-value      [0] Double,
1811  *      status-flags         [1] BACnetStatusFlags
1812  *      deadband             [2] Double,
1813  *      exceeded-limit       [3] Double
1814  *      },
1815  *  signed-out-of-range [15]    SEQUENCE {
1816  *      exceeding-value      [0] INTEGER,
1817  *      status-flags         [1] BACnetStatusFlags
1818  *      deadband             [2] Unsigned,
1819  *      exceeded-limit       [3] INTEGER
1820  *      },
1821  *  unsigned-out-of-range [16]    SEQUENCE {
1822  *      exceeding-value      [0] Unsigned,
1823  *      status-flags         [1] BACnetStatusFlags
1824  *      deadband             [2] Unsigned,
1825  *      exceeded-limit       [3] Unsigned
1826  *      },
1827  *  change-of-characterstring [17]    SEQUENCE {
1828  *      changed-value        [0] CharacterString,
1829  *      status-flags         [1] BACnetStatusFlags
1830  *      alarm-value          [2] CharacterString
1831  *      },
1832  *  change-of-status-flags [18]    SEQUENCE {
1833  *      present-value        [0] ABSTRACT-SYNTAX.&Type OPTIONAL,
1834  *                              -- depends on referenced property
1835  *      referenced-flags     [1] BACnetStatusFlags
1836  *      },
1837  * }
1838  * @param tvb the tv buffer of the current data
1839  * @param pinfo the packet info of the current data
1840  * @param tree the tree to append this item to
1841  * @param offset the offset in the tvb
1842  * @return modified offset
1843  */
1844 static guint
1845 fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1846
1847 /**
1848  * BACnetObjectPropertyReference ::= SEQUENCE {
1849  *  objectIdentifier    [0] BACnetObjectIdentifier,
1850  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1851  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
1852  * }
1853  * @param tvb the tv buffer of the current data
1854  * @param pinfo the packet info of the current data
1855  * @param tree the tree to append this item to
1856  * @param offset the offset in the tvb
1857  * @return modified offset
1858  */
1859 static guint
1860 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1861
1862 #if 0
1863 /**
1864  * BACnetObjectPropertyValue ::= SEQUENCE {
1865  *      objectIdentifier   [0] BACnetObjectIdentifier,
1866  *      propertyIdentifier [1] BACnetPropertyIdentifier,
1867  *      propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
1868  *                                                -- if omitted with an array the entire array is referenced
1869  *      value              [3] ABSTRACT-SYNTAX.&Type, --any datatype appropriate for the specified property
1870  *      priority           [4] Unsigned (1..16) OPTIONAL
1871  * }
1872  * @param tvb the tv buffer of the current data
1873  * @param tree the tree to append this item to
1874  * @param offset the offset in the tvb
1875  * @return modified offset
1876  */
1877 static guint
1878 fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, guint offset);
1879 #endif
1880
1881 /**
1882  * BACnetPriorityArray ::= SEQUENCE SIZE (16) OF BACnetPriorityValue
1883  * @param tvb the tv buffer of the current data
1884  * @param pinfo the packet info of the current data
1885  * @param tree the tree to append this item to
1886  * @param offset the offset in the tvb
1887  * @return modified offset
1888  */
1889 static guint
1890 fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1891
1892 static guint
1893 fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list);
1894
1895 /**
1896  * BACnetPropertyReference ::= SEQUENCE {
1897  *  propertyIdentifier  [0] BACnetPropertyIdentifier,
1898  *  propertyArrayIndex  [1] Unsigned OPTIONAL, -- used only with array datatype
1899  * }
1900  * @param tvb the tv buffer of the current data
1901  * @param pinfo the packet info of the current data
1902  * @param tree the tree to append this item to
1903  * @param offset the offset in the tvb
1904  * @return modified offset
1905  */
1906 static guint
1907 fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list);
1908
1909 /* static guint
1910 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset); */
1911
1912 static guint
1913 fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1914
1915 static guint
1916 fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1917
1918 /**
1919  * BACnetPropertyValue ::= SEQUENCE {
1920  *      PropertyIdentifier [0] BACnetPropertyIdentifier,
1921  *      propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatypes
1922  *                                                -- if omitted with an array the entire array is referenced
1923  *      value              [2] ABSTRACT-SYNTAX.&Type, -- any datatype appropriate for the specified property
1924  *      priority           [3] Unsigned (1..16) OPTIONAL -- used only when property is commandable
1925  * }
1926  * @param tvb the tv buffer of the current data
1927  * @param pinfo the packet info of the current data
1928  * @param tree the tree to append this item to
1929  * @param offset the offset in the tvb
1930  * @return modified offset
1931  */
1932 static guint
1933 fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1934
1935 static guint
1936 fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset);
1937
1938 /**
1939  * BACnet Application PDUs chapter 21
1940  * BACnetRecipient::= CHOICE {
1941  *  device  [0] BACnetObjectIdentifier
1942  *  address [1] BACnetAddress
1943  * }
1944  * @param tvb the tv buffer of the current data
1945  * @param pinfo the packet info of the current data
1946  * @param tree the tree to append this item to
1947  * @param offset the offset in the tvb
1948  * @return modified offset
1949  */
1950 static guint
1951 fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1952
1953 /**
1954  * BACnet Application PDUs chapter 21
1955  * BACnetRecipientProcess::= SEQUENCE {
1956  *  recipient   [0] BACnetRecipient
1957  *  processID   [1] Unsigned32
1958  * }
1959  * @param tvb the tv buffer of the current data
1960  * @param pinfo the packet info of the current data
1961  * @param tree the tree to append this item to
1962  * @param offset the offset in the tvb
1963  * @return modified offset
1964  */
1965 static guint
1966 fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1967
1968 static guint
1969 fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1970
1971 #if 0
1972 /**
1973  * BACnetSessionKey ::= SEQUENCE {
1974  *  sessionKey  OCTET STRING (SIZE(8)), -- 56 bits for key, 8 bits for checksum
1975  *  peerAddress BACnetAddress
1976  * }
1977  * @param tvb the tv buffer of the current data
1978  * @param tree the tree to append this item to
1979  * @param offset the offset in the tvb
1980  * @return modified offset
1981  * @todo check if checksum is displayed correctly
1982  */
1983 static guint
1984 fSessionKey(tvbuff_t *tvb, proto_tree *tree, guint offset);
1985 #endif
1986
1987 /**
1988  * BACnetSpecialEvent ::= SEQUENCE {
1989  *  period      CHOICE {
1990  *      calendarEntry       [0] BACnetCalendarEntry,
1991  *      calendarRefernce    [1] BACnetObjectIdentifier
1992  *      },
1993  *      listOfTimeValues    [2] SEQUENCE OF BACnetTimeValue,
1994  *      eventPriority       [3] Unsigned (1..16)
1995  * }
1996  * @param tvb the tv buffer of the current data
1997  * @param pinfo the packet info of the current data
1998  * @param tree the tree to append this item to
1999  * @param offset the offset in the tvb
2000  * @return modified offset
2001  */
2002 static guint
2003 fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2004
2005 /**
2006  * BACnetTimeStamp ::= CHOICE {
2007  *  time            [0] Time,
2008  *  sequenceNumber  [1] Unsigned (0..65535),
2009  *  dateTime        [2] BACnetDateTime
2010  * }
2011  * @param tvb the tv buffer of the current data
2012  * @param pinfo the packet info of the current data
2013  * @param tree the tree to append this item to
2014  * @param offset the offset in the tvb
2015  * @param label the label of this item
2016  * @return modified offset
2017  */
2018 static guint
2019 fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2020
2021 static guint
2022 fEventTimeStamps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2023
2024 /**
2025  * BACnetTimeValue ::= SEQUENCE {
2026  *  time    Time,
2027  *  value   ABSTRACT-SYNTAX.&Type -- any primitive datatype, complex types cannot be decoded
2028  * }
2029  * @param tvb the tv buffer of the current data
2030  * @param pinfo the packet info of the current data
2031  * @param tree the tree to append this item to
2032  * @param offset the offset in the tvb
2033  * @return modified offset
2034  */
2035 static guint
2036 fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2037
2038 #if 0
2039 /**
2040  * BACnetVTSession ::= SEQUENCE {
2041  *  local-vtSessionID   Unsigned8,
2042  *  remote-vtSessionID  Unsigned8,
2043  *  remote-vtAddress    BACnetAddress
2044  * }
2045  * @param tvb the tv buffer of the current data
2046  * @param tree the tree to append this item to
2047  * @param offset the offset in the tvb
2048  * @return modified offset
2049  */
2050 static guint
2051 fVTSession(tvbuff_t *tvb, proto_tree *tree, guint offset);
2052 #endif
2053
2054 /**
2055  * BACnetWeekNDay ::= OCTET STRING (SIZE (3))
2056  * -- first octet month (1..12) January = 1, X'FF' = any month
2057  * -- second octet weekOfMonth where: 1 = days numbered 1-7
2058  * -- 2 = days numbered 8-14
2059  * -- 3 = days numbered 15-21
2060  * -- 4 = days numbered 22-28
2061  * -- 5 = days numbered 29-31
2062  * -- 6 = last 7 days of this month
2063  * -- X'FF' = any week of this month
2064  * -- third octet dayOfWeek (1..7) where 1 = Monday
2065  * -- 7 = Sunday
2066  * -- X'FF' = any day of week
2067  * @param tvb the tv buffer of the current data
2068  * @param pinfo the packet info of the current data
2069  * @param tree the tree to append this item to
2070  * @param offset the offset in the tvb
2071  * @return modified offset
2072  */
2073 static guint
2074 fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2075
2076 /**
2077  * ReadAccessResult ::= SEQUENCE {
2078  *  objectIdentifier            [0] BACnetObjectIdentifier,
2079  *  listOfResults               [1] SEQUENCE OF SEQUENCE {
2080  *      propertyIdentifier      [2] BACnetPropertyIdentifier,
2081  *      propertyArrayIndex      [3] Unsigned OPTIONAL, -- used only with array datatype if omitted with an array the entire array is referenced
2082  *      readResult  CHOICE {
2083  *          propertyValue       [4] ABSTRACT-SYNTAX.&Type,
2084  *          propertyAccessError [5] Error
2085  *      }
2086  *  } OPTIONAL
2087  * }
2088  * @param tvb the tv buffer of the current data
2089  * @param pinfo the packet info of the current data
2090  * @param tree the tree to append this item to
2091  * @param offset the offset in the tvb
2092  * @return modified offset
2093  */
2094 static guint
2095 fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2096
2097 /**
2098  * ReadAccessSpecification ::= SEQUENCE {
2099  *  objectIdentifier         [0] BACnetObjectIdentifier,
2100  *  listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference
2101  * }
2102  * @param tvb the tv buffer of the current data
2103  * @param pinfo the packet info of the current data
2104  * @param subtree the subtree to append this item to
2105  * @param offset the offset in the tvb
2106  * @return modified offset
2107  */
2108 static guint
2109 fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2110
2111 /**
2112  * WriteAccessSpecification ::= SEQUENCE {
2113  *  objectIdentifier [0] BACnetObjectIdentifier,
2114  *  listOfProperty   [1] SEQUENCE OF BACnetPropertyValue
2115  * }
2116  * @param tvb the tv buffer of the current data
2117  * @param pinfo the packet info of the current data
2118  * @param subtree the sub tree to append this item to
2119  * @param offset the offset in the tvb
2120  * @return modified offset
2121  */
2122 static guint
2123 fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2124
2125
2126 /********************************************************* Helper functions *******************************************/
2127
2128 /**
2129  * extracts the tag number from the tag header.
2130  * @param tvb the tv buffer of the current data "TestyVirtualBuffer"
2131  * @param offset the offset in the tvb in actual tvb
2132  * @return Tag Number corresponding to BACnet 20.2.1.2 Tag Number
2133  */
2134 static guint
2135 fTagNo(tvbuff_t *tvb, guint offset);
2136
2137 /**
2138  * splits Tag Header coresponding to 20.2.1 General Rules For BACnet Tags
2139  * @param tvb the tv buffer of the current data = "TestyVirtualBuffer"
2140  * @param pinfo the packet info of the current data = packet info
2141  * @param offset the offset in the tvb = offset in actual tvb
2142  * @return tag_no BACnet 20.2.1.2 Tag Number
2143  * @return class_tag BACnet 20.2.1.1 Class
2144  * @return lvt BACnet 20.2.1.3 Length/Value/Type
2145  * @return offs = length of this header
2146  */
2147
2148 static guint
2149 fTagHeader(tvbuff_t *tvb, packet_info *pinfo, guint offset, guint8 *tag_no, guint8* class_tag, guint32 *lvt);
2150
2151
2152 /**
2153  * adds processID with max 32Bit unsigned Integer Value to tree
2154  * @param tvb the tv buffer of the current data
2155  * @param pinfo the packet info of the current data
2156  * @param tree the tree to append this item to
2157  * @param offset the offset in the tvb
2158  * @return modified offset
2159  */
2160 static guint
2161 fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2162
2163 /**
2164  * adds timeSpan with max 32Bit unsigned Integer Value to tree
2165  * @param tvb the tv buffer of the current data
2166  * @param pinfo the packet info of the current data
2167  * @param tree the tree to append this item to
2168  * @param offset the offset in the tvb
2169  * @return modified offset
2170  */
2171 static guint
2172 fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2173
2174 /**
2175  * BACnet Application PDUs chapter 21
2176  * BACnetPropertyIdentifier::= ENUMERATED {
2177  *   @see bacapp_property_identifier
2178  * }
2179  * @param tvb the tv buffer of the current data
2180  * @param pinfo the packet info of the current data
2181  * @param tree the tree to append this item to
2182  * @param offset the offset in the tvb
2183  * @return modified offset
2184  */
2185 static guint
2186 fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2187
2188 /**
2189  * BACnet Application PDUs chapter 21
2190  * BACnetPropertyArrayIndex::= ENUMERATED {
2191  *   @see bacapp_property_array_index
2192  * }
2193  * @param tvb the tv buffer of the current data
2194  * @param pinfo the packet info of the current data
2195  * @param tree the tree to append this item to
2196  * @param offset the offset in the tvb
2197  * @return modified offset
2198  */
2199 static guint
2200 fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2201
2202 /**
2203  * listOfEventSummaries ::= SEQUENCE OF SEQUENCE {
2204  *  objectIdentifier        [0] BACnetObjectIdentifier,
2205  *  eventState              [1] BACnetEventState,
2206  *  acknowledgedTransitions [2] BACnetEventTransitionBits,
2207  *  eventTimeStamps         [3] SEQURNCE SIZE (3) OF BACnetTimeStamps,
2208  *  notifyType              [4] BACnetNotifyType,
2209  *  eventEnable             [5] BACnetEventTransitionBits,
2210  *  eventPriorities         [6] SEQUENCE SIZE (3) OF Unsigned
2211  * }
2212  * @param tvb the tv buffer of the current data
2213  * @param pinfo the packet info of the current data
2214  * @param tree the tree to append this item to
2215  * @param offset the offset in the tvb
2216  * @return modified offset
2217  */
2218 static guint
2219 flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2220
2221 /**
2222  * SelectionCriteria ::= SEQUENCE {
2223  *  propertyIdentifier [0] BACnetPropertyIdentifier,
2224  *  propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatype
2225  *  relationSpecifier  [2] ENUMERATED { bacapp_relationSpecifier },
2226  *  comparisonValue    [3] ABSTRACT-SYNTAX.&Type
2227  * }
2228  * @param tvb the tv buffer of the current data
2229  * @param pinfo the packet info of the current data
2230  * @param tree the tree to append this item to
2231  * @param offset the offset in the tvb
2232  * @return modified offset
2233  */
2234 static guint
2235 fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2236
2237 /**
2238  * objectSelectionCriteria ::= SEQUENCE {
2239  *  selectionLogic          [0] ENUMERATED { bacapp_selectionLogic },
2240  *  listOfSelectionCriteria [1] SelectionCriteria
2241  * }
2242  * @param tvb the tv buffer of the current data
2243  * @param pinfo the packet info of the current data
2244  * @param subtree the sub tree to append this item to
2245  * @param offset the offset in the tvb
2246  * @return modified offset
2247  */
2248 static guint
2249 fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2250
2251 /**
2252  * BACnet-Error ::= SEQUENCE {
2253  *    error-class ENUMERATED {},
2254  *    error-code  ENUMERATED {}
2255  *    }
2256  * }
2257  * @param tvb the tv buffer of the current data
2258  * @param pinfo the packet info of the current data
2259  * @param tree the tree to append this item to
2260  * @param offset the offset in the tvb
2261  * @return modified offset
2262  */
2263 static guint
2264 fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2265
2266 /**
2267  * Generic handler for context tagged values.  Mostly for handling
2268  * vendor-defined properties and services.
2269  * @param tvb the tv buffer of the current data
2270  * @param pinfo the packet info of the current data
2271  * @param tree the tree to append this item to
2272  * @param offset the offset in the tvb
2273  * @return modified offset
2274  * @todo beautify this ugly construct
2275  */
2276 static guint
2277 fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2278
2279 /**
2280  * realizes some ABSTRACT-SYNTAX.&Type
2281  * @param tvb the tv buffer of the current data
2282  * @param pinfo the packet info of the current data
2283  * @param tree the tree to append this item to
2284  * @param offset the offset in the tvb
2285  * @return modified offset
2286  * @todo beautify this ugly construct
2287  */
2288 static guint
2289 fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2290
2291
2292 static guint
2293 fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label,
2294     const value_string *src);
2295
2296 /**
2297  * register_bacapp
2298  */
2299 void
2300 proto_register_bacapp(void);
2301
2302 /**
2303  * proto_reg_handoff_bacapp
2304  */
2305 void
2306 proto_reg_handoff_bacapp(void);
2307
2308 /* <<<< formerly bacapp.h */
2309
2310 /* reassembly table for segmented messages */
2311 static reassembly_table msg_reassembly_table;
2312
2313 /* some necessary forward function prototypes */
2314 static guint
2315 fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
2316     const gchar *label, const value_string *vs);
2317
2318 static const char *bacapp_unknown_service_str = "unknown service";  /* Usage: no format specifiers */
2319 static const char ASHRAE_Reserved_Fmt[] = "(%d) Reserved for Use by ASHRAE";
2320 static const char Vendor_Proprietary_Fmt[] = "(%d) Vendor Proprietary Value";
2321
2322 static const value_string
2323 BACnetTypeName[] = {
2324     { 0, "Confirmed-REQ"},
2325     { 1, "Unconfirmed-REQ"},
2326     { 2, "Simple-ACK"},
2327     { 3, "Complex-ACK"},
2328     { 4, "Segment-ACK"},
2329     { 5, "Error"},
2330     { 6, "Reject"},
2331     { 7, "Abort"},
2332     { 0, NULL }
2333 };
2334
2335 static const true_false_string segments_follow = {
2336     "Segmented Request",
2337     "Unsegmented Request"
2338 };
2339
2340 static const true_false_string more_follow = {
2341     "More Segments Follow",
2342     "No More Segments Follow"
2343 };
2344
2345 static const true_false_string segmented_accept = {
2346     "Segmented Response accepted",
2347     "Segmented Response not accepted"
2348 };
2349
2350 static const true_false_string
2351 BACnetTagClass = {
2352     "Context Specific Tag",
2353     "Application Tag"
2354 };
2355
2356 static const value_string
2357 BACnetMaxSegmentsAccepted [] = {
2358     { 0,  "Unspecified"},
2359     { 1,  "2 segments"},
2360     { 2,  "4 segments"},
2361     { 3,  "8 segments"},
2362     { 4, "16 segments"},
2363     { 5, "32 segments"},
2364     { 6, "64 segments"},
2365     { 7, "Greater than 64 segments"},
2366     { 0, NULL }
2367 };
2368
2369 static const value_string
2370 BACnetMaxAPDULengthAccepted [] = {
2371     {  0, "Up to MinimumMessageSize (50 octets)"},
2372     {  1, "Up to 128 octets"},
2373     {  2, "Up to 206 octets (fits in a LonTalk frame)"},
2374     {  3, "Up to 480 octets (fits in an ARCNET frame)"},
2375     {  4, "Up to 1024 octets"},
2376     {  5, "Up to 1476 octets (fits in an ISO 8802-3 frame)"},
2377     {  6, "reserved by ASHRAE"},
2378     {  7, "reserved by ASHRAE"},
2379     {  8, "reserved by ASHRAE"},
2380     {  9, "reserved by ASHRAE"},
2381     { 10, "reserved by ASHRAE"},
2382     { 11, "reserved by ASHRAE"},
2383     { 12, "reserved by ASHRAE"},
2384     { 13, "reserved by ASHRAE"},
2385     { 14, "reserved by ASHRAE"},
2386     { 15, "reserved by ASHRAE"},
2387     { 0, NULL}
2388 };
2389
2390 static const value_string
2391 BACnetRejectReason [] = {
2392     {0, "other"},
2393     {1, "buffer-overflow"},
2394     {2, "inconsistent-parameters"},
2395     {3, "invalid-parameter-data-type"},
2396     {4, "invalid-tag"},
2397     {5, "missing-required-parameter"},
2398     {6, "parameter-out-of-range"},
2399     {7, "too-many-arguments"},
2400     {8, "undefined-enumeration"},
2401     {9, "unrecognized-service"},
2402     {0, NULL}
2403 };
2404
2405 static const value_string
2406 BACnetRestartReason [] = {
2407     { 0, "unknown"},
2408     { 1, "coldstart"},
2409     { 2, "warmstart"},
2410     { 3, "detected-power-lost"},
2411     { 4, "detected-powered-off"},
2412     { 5, "hardware-watchdog"},
2413     { 6, "software-watchdog"},
2414     { 7, "suspended"},
2415     { 0, NULL}
2416 };
2417
2418 static const value_string
2419 BACnetApplicationTagNumber [] = {
2420     {  0, "Null"},
2421     {  1, "Boolean"},
2422     {  2, "Unsigned Integer"},
2423     {  3, "Signed Integer (2's complement notation)"},
2424     {  4, "Real (ANSI/IEE-754 floating point)"},
2425     {  5, "Double (ANSI/IEE-754 double precision floating point)"},
2426     {  6, "Octet String"},
2427     {  7, "Character String"},
2428     {  8, "Bit String"},
2429     {  9, "Enumerated"},
2430     { 10, "Date"},
2431     { 11, "Time"},
2432     { 12, "BACnetObjectIdentifier"},
2433     { 13, "reserved by ASHRAE"},
2434     { 14, "reserved by ASHRAE"},
2435     { 15, "reserved by ASHRAE"},
2436     { 0,  NULL}
2437 };
2438
2439 static const value_string
2440 BACnetAction [] = {
2441     { 0, "direct"},
2442     { 1, "reverse"},
2443     { 0, NULL}
2444 };
2445
2446 static const value_string
2447 BACnetAccessEvent [] = {
2448     {  0, "none"},
2449     {  1, "granted"},
2450     {  2, "muster"},
2451     {  3, "passback-detected"},
2452     {  4, "duress"},
2453     {  5, "trace"},
2454     {  6, "lockout-max-attempts"},
2455     {  7, "lockout-other"},
2456     {  8, "lockout-relinquished"},
2457     {  9, "lockout-by-higher-priority"},
2458     { 10, "out-of-service"},
2459     { 11, "out-of-service-relinquished"},
2460     { 12, "accompaniment-by"},
2461     { 13, "authentication-factor-read"},
2462     { 14, "authorization-delayed"},
2463     { 15, "verification-required"},
2464     /* Enumerated values 128-511 are used for events
2465      * which indicate that access has been denied. */
2466     { 128, "denied-deny-all"},
2467     { 129, "denied-unknown-credential"},
2468     { 130, "denied-authentication-unavailable"},
2469     { 131, "denied-authentication-factor-timeout"},
2470     { 132, "denied-incorrect-authentication-factor"},
2471     { 133, "denied-zone-no-access-rights"},
2472     { 134, "denied-point-no-access-rights"},
2473     { 135, "denied-no-access-rights"},
2474     { 136, "denied-out-of-time-range"},
2475     { 137, "denied-threat-level"},
2476     { 138, "denied-passback"},
2477     { 139, "denied-unexpected-location-usage"},
2478     { 140, "denied-max-attempts"},
2479     { 141, "denied-lower-occupancy-limit"},
2480     { 142, "denied-upper-occupancy-limit"},
2481     { 143, "denied-authentication-factor-lost"},
2482     { 144, "denied-authentication-factor-stolen"},
2483     { 145, "denied-authentication-factor-damaged"},
2484     { 146, "denied-authentication-factor-destroyed"},
2485     { 147, "denied-authentication-factor-disabled"},
2486     { 148, "denied-authentication-factor-error"},
2487     { 149, "denied-credential-unassigned"},
2488     { 150, "denied-credential-not-provisioned"},
2489     { 151, "denied-credential-not-yet-active"},
2490     { 152, "denied-credential-expired"},
2491     { 153, "denied-credential-manual-disable"},
2492     { 154, "denied-credential-lockout"},
2493     { 155, "denied-credential-max-days"},
2494     { 156, "denied-credential-max-uses"},
2495     { 157, "denied-credential-inactivity"},
2496     { 158, "denied-credential-disabled"},
2497     { 159, "denied-no-accompaniment"},
2498     { 160, "denied-incorrect-accompaniment"},
2499     { 161, "denied-lockout"},
2500     { 162, "denied-verification-failed"},
2501     { 163, "denied-verification-timeout"},
2502     { 164, "denied-other"},
2503     { 0,  NULL}
2504 /* Enumerated values 0-512 are reserved for definition by ASHRAE.
2505    Enumerated values 512-65535 may be used by others subject to
2506    procedures and constraints described in Clause 23. */
2507 };
2508
2509 static const value_string
2510 BACnetFileAccessMethod [] = {
2511     { 0, "record-access"},
2512     { 1, "stream-access"},
2513     { 0, NULL}
2514 };
2515
2516 /* For some reason, BACnet defines the choice parameter
2517    in the file read and write services backwards from the
2518    BACnetFileAccessMethod enumeration.
2519 */
2520 static const value_string
2521 BACnetFileAccessOption [] = {
2522     { 0, "stream access"},
2523     { 1, "record access"},
2524     { 0, NULL}
2525 };
2526
2527 static const value_string
2528 BACnetFileStartOption [] = {
2529     { 0, "File Start Position: "},
2530     { 1, "File Start Record: "},
2531     { 0, NULL}
2532 };
2533
2534 static const value_string
2535 BACnetFileRequestCount [] = {
2536     { 0, "Requested Octet Count: "},
2537     { 1, "Requested Record Count: "},
2538     { 0, NULL}
2539 };
2540
2541 static const value_string
2542 BACnetFileWriteInfo [] = {
2543     { 0, "File Data: "},
2544     { 1, "Record Count: "},
2545     { 0, NULL}
2546 };
2547
2548 static const value_string
2549 BACnetAbortReason [] = {
2550     { 0, "other"},
2551     { 1, "buffer-overflow"},
2552     { 2, "invalid-apdu-in-this-state"},
2553     { 3, "preempted-by-higher-priority-task"},
2554     { 4, "segmentation-not-supported"},
2555     { 0, NULL}
2556 };
2557
2558 static const value_string
2559 BACnetLifeSafetyMode [] = {
2560     {  0, "off"},
2561     {  1, "on"},
2562     {  2, "test"},
2563     {  3, "manned"},
2564     {  4, "unmanned"},
2565     {  5, "armed"},
2566     {  6, "disarmed"},
2567     {  7, "prearmed"},
2568     {  8, "slow"},
2569     {  9, "fast"},
2570     { 10, "disconnected"},
2571     { 11, "enabled"},
2572     { 12, "disabled"},
2573     { 13, "atomic-release-disabled"},
2574     { 14, "default"},
2575     { 0,  NULL}
2576 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2577    Enumerated values 256-65535 may be used by others subject to
2578    procedures and constraints described in Clause 23. */
2579 };
2580
2581 static const value_string
2582 BACnetLifeSafetyOperation [] = {
2583     { 0, "none"},
2584     { 1, "silence"},
2585     { 2, "silence-audible"},
2586     { 3, "silence-visual"},
2587     { 4, "reset"},
2588     { 5, "reset-alarm"},
2589     { 6, "reset-fault"},
2590     { 7, "unsilence"},
2591     { 8, "unsilence-audible"},
2592     { 9, "unsilence-visual"},
2593     { 0, NULL}
2594 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
2595    Enumerated values 64-65535 may be used by others subject to
2596    procedures and constraints described in Clause 23. */
2597 };
2598
2599 #if 0
2600 static const value_string
2601 BACnetLimitEnable [] = {
2602     { 0, "lowLimitEnable"},
2603     { 1, "highLimitEnable"},
2604     { 0, NULL}
2605 };
2606 #endif
2607
2608 static const value_string
2609 BACnetLifeSafetyState [] = {
2610     {  0, "quiet"},
2611     {  1, "pre-alarm"},
2612     {  2, "alarm"},
2613     {  3, "fault"},
2614     {  4, "fault-pre-alarm"},
2615     {  5, "fault-alarm"},
2616     {  6, "not-ready"},
2617     {  7, "active"},
2618     {  8, "tamper"},
2619     {  9, "test-alarm"},
2620     { 10, "test-active"},
2621     { 11, "test-fault"},
2622     { 12, "test-fault-alarm"},
2623     { 13, "holdup"},
2624     { 14, "duress"},
2625     { 15, "tamper-alarm"},
2626     { 16, "abnormal"},
2627     { 17, "emergency-power"},
2628     { 18, "delayed"},
2629     { 19, "blocked"},
2630     { 20, "local-alarm"},
2631     { 21, "general-alarm"},
2632     { 22, "supervisory"},
2633     { 23, "test-supervisory"},
2634     { 0,  NULL}
2635 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2636    Enumerated values 256-65535 may be used by others subject to
2637    procedures and constraints described in Clause 23. */
2638 };
2639
2640 static const value_string
2641 BACnetConfirmedServiceChoice [] = {
2642     {  0, "acknowledgeAlarm"},
2643     {  1, "confirmedCOVNotification"},
2644     {  2, "confirmedEventNotification"},
2645     {  3, "getAlarmSummary"},
2646     {  4, "getEnrollmentSummary"},
2647     {  5, "subscribeCOV"},
2648     {  6, "atomicReadFile"},
2649     {  7, "atomicWriteFile"},
2650     {  8, "addListElement"},
2651     {  9, "removeListElement"},
2652     { 10, "createObject"},
2653     { 11, "deleteObject"},
2654     { 12, "readProperty"},
2655     { 13, "readPropertyConditional"},
2656     { 14, "readPropertyMultiple"},
2657     { 15, "writeProperty"},
2658     { 16, "writePropertyMultiple"},
2659     { 17, "deviceCommunicationControl"},
2660     { 18, "confirmedPrivateTransfer"},
2661     { 19, "confirmedTextMessage"},
2662     { 20, "reinitializeDevice"},
2663     { 21, "vtOpen"},
2664     { 22, "vtClose"},
2665     { 23, "vtData"},
2666     { 24, "authenticate"},
2667     { 25, "requestKey"},
2668     { 26, "readRange"},
2669     { 27, "lifeSafetyOperation"},
2670     { 28, "subscribeCOVProperty"},
2671     { 29, "getEventInformation"},
2672     { 30, "reserved by ASHRAE"},
2673     { 0,  NULL}
2674 };
2675
2676 static const value_string
2677 BACnetReliability [] = {
2678     {  0, "no-fault-detected"},
2679     {  1, "no-sensor"},
2680     {  2, "over-range"},
2681     {  3, "under-range"},
2682     {  4, "open-loop"},
2683     {  5, "shorted-loop"},
2684     {  6, "no-output"},
2685     {  7, "unreliable-other"},
2686     {  8, "process-error"},
2687     {  9, "multi-state-fault"},
2688     { 10, "configuration-error"},
2689     /* enumeration value 11 is reserved for a future addendum */
2690     { 12, "communication-failure"},
2691     { 13, "member-fault"},
2692     { 0,  NULL}
2693 };
2694
2695 static const value_string
2696 BACnetUnconfirmedServiceChoice [] = {
2697     { 0, "i-Am"},
2698     { 1, "i-Have"},
2699     { 2, "unconfirmedCOVNotification"},
2700     { 3, "unconfirmedEventNotification"},
2701     { 4, "unconfirmedPrivateTransfer"},
2702     { 5, "unconfirmedTextMessage"},
2703     { 6, "timeSynchronization"},
2704     { 7, "who-Has"},
2705     { 8, "who-Is"},
2706     { 9, "utcTimeSynchronization"},
2707     { 0, NULL}
2708 };
2709
2710 #if 0
2711 static const value_string
2712 BACnetUnconfirmedServiceRequest [] = {
2713     { 0, "i-Am-Request"},
2714     { 1, "i-Have-Request"},
2715     { 2, "unconfirmedCOVNotification-Request"},
2716     { 3, "unconfirmedEventNotification-Request"},
2717     { 4, "unconfirmedPrivateTransfer-Request"},
2718     { 5, "unconfirmedTextMessage-Request"},
2719     { 6, "timeSynchronization-Request"},
2720     { 7, "who-Has-Request"},
2721     { 8, "who-Is-Request"},
2722     { 9, "utcTimeSynchonization-Request"},
2723     { 0, NULL}
2724 };
2725 #endif
2726
2727 static const value_string
2728 BACnetObjectType [] = {
2729     {  0, "analog-input"},
2730     {  1, "analog-output"},
2731     {  2, "analog-value"},
2732     {  3, "binary-input"},
2733     {  4, "binary-output"},
2734     {  5, "binary-value"},
2735     {  6, "calendar"},
2736     {  7, "command"},
2737     {  8, "device"},
2738     {  9, "event-enrollment"},
2739     { 10, "file"},
2740     { 11, "group"},
2741     { 12, "loop"},
2742     { 13, "multi-state-input"},
2743     { 14, "multi-state-output"},
2744     { 15, "notification-class"},
2745     { 16, "program"},
2746     { 17, "schedule"},
2747     { 18, "averaging"},
2748     { 19, "multi-state-value"},
2749     { 20, "trend-log"},
2750     { 21, "life-safety-point"},
2751     { 22, "life-safety-zone"},
2752     { 23, "accumulator"},
2753     { 24, "pulse-converter"},
2754     { 25, "event-log"},
2755     { 26, "global-group"},
2756     { 27, "trend-log-multiple"},
2757     { 28, "load-control"},
2758     { 29, "structured-view"},
2759     { 30, "access-door"},     /* 30-37 added with addanda 135-2008j */
2760     /* value 31 is unassigned */
2761     { 32, "access-credential"},
2762     { 33, "access-point"},
2763     { 34, "access-rights"},
2764     { 35, "access-user"},
2765     { 36, "access-zone"},
2766     { 37, "credential-data-input"},
2767     { 38, "network-security"},
2768     { 39, "bitstring-value"},     /* 39-50 added with addenda 135-2008w */
2769     { 40, "characterstring-value"},
2770     { 41, "date-pattern-value"},
2771     { 42, "date-value"},
2772     { 43, "datetime-pattern-value"},
2773     { 44, "datetime-value"},
2774     { 45, "integer-value"},
2775     { 46, "large-analog-value"},
2776     { 47, "octetstring-value"},
2777     { 48, "positive-integer-value"},
2778     { 49, "time-pattern-value"},
2779     { 50, "time-value"},
2780     { 0,  NULL}
2781 /* Enumerated values 0-127 are reserved for definition by ASHRAE.
2782    Enumerated values 128-1023 may be used by others subject to
2783    the procedures and constraints described in Clause 23. */
2784 };
2785
2786 static const value_string
2787 BACnetEngineeringUnits [] = {
2788     {   0, "Sq Meters"},
2789     {   1, "Sq Feet"},
2790     {   2, "Milliamperes"},
2791     {   3, "Amperes"},
2792     {   4, "Ohms"},
2793     {   5, "Volts"},
2794     {   6, "Kilovolts"},
2795     {   7, "Megavolts"},
2796     {   8, "Volt Amperes"},
2797     {   9, "Kilovolt Amperes"},
2798     {  10, "Megavolt Amperes"},
2799     {  11, "Volt Amperes Reactive"},
2800     {  12, "Kilovolt Amperes Reactive"},
2801     {  13, "Megavolt Amperes Reactive"},
2802     {  14, "Degrees Phase"},
2803     {  15, "Power Factor"},
2804     {  16, "Joules"},
2805     {  17, "Kilojoules"},
2806     {  18, "Watt Hours"},
2807     {  19, "Kilowatt Hours"},
2808     {  20, "BTUs"},
2809     {  21, "Therms"},
2810     {  22, "Ton Hours"},
2811     {  23, "Joules Per Kg Dry Air"},
2812     {  24, "BTUs Per Pound Dry Air"},
2813     {  25, "Cycles Per Hour"},
2814     {  26, "Cycles Per Minute"},
2815     {  27, "Hertz"},
2816     {  28, "Grams Of Water Per Kilogram Dry Air"},
2817     {  29, "Relative Humidity"},
2818     {  30, "Millimeters"},
2819     {  31, "Meters"},
2820     {  32, "Inches"},
2821     {  33, "Feed"},
2822     {  34, "Watts Per Sq Foot"},
2823     {  35, "Watts Per Sq meter"},
2824     {  36, "Lumens"},
2825     {  37, "Lux"},
2826     {  38, "Foot Candles"},
2827     {  39, "Kilograms"},
2828     {  40, "Pounds Mass"},
2829     {  41, "Tons"},
2830     {  42, "Kgs per Second"},
2831     {  43, "Kgs Per Minute"},
2832     {  44, "Kgs Per Hour"},
2833     {  45, "Pounds Mass Per Minute"},
2834     {  46, "Pounds Mass Per Hour"},
2835     {  47, "Watt"},
2836     {  48, "Kilowatts"},
2837     {  49, "Megawatts"},
2838     {  50, "BTUs Per Hour"},
2839     {  51, "Horsepower"},
2840     {  52, "Tons Refrigeration"},
2841     {  53, "Pascals"},
2842     {  54, "Kilopascals"},
2843     {  55, "Bars"},
2844     {  56, "Pounds Force Per Square Inch"},
2845     {  57, "Centimeters Of Water"},
2846     {  58, "Inches Of Water"},
2847     {  59, "Millimeters Of Mercury"},
2848     {  60, "Centimeters Of Mercury"},
2849     {  61, "Inches Of Mercury"},
2850     {  62, "Degrees Celsius"},
2851     {  63, "Degrees Kelvin"},
2852     {  64, "Degrees Fahrenheit"},
2853     {  65, "Degree Days Celsius"},
2854     {  66, "Degree Days Fahrenheit"},
2855     {  67, "Years"},
2856     {  68, "Months"},
2857     {  69, "Weeks"},
2858     {  70, "Days"},
2859     {  71, "Hours"},
2860     {  72, "Minutes"},
2861     {  73, "Seconds"},
2862     {  74, "Meters Per Second"},
2863     {  75, "Kilometers Per Hour"},
2864     {  76, "Feed Per Second"},
2865     {  77, "Feet Per Minute"},
2866     {  78, "Miles Per Hour"},
2867     {  79, "Cubic Feet"},
2868     {  80, "Cubic Meters"},
2869     {  81, "Imperial Gallons"},
2870     {  82, "Liters"},
2871     {  83, "US Gallons"},
2872     {  84, "Cubic Feet Per Minute"},
2873     {  85, "Cubic Meters Per Second"},
2874     {  86, "Imperial Gallons Per Minute"},
2875     {  87, "Liters Per Second"},
2876     {  88, "Liters Per Minute"},
2877     {  89, "US Gallons Per Minute"},
2878     {  90, "Degrees Angular"},
2879     {  91, "Degrees Celsius Per Hour"},
2880     {  92, "Degrees Celsius Per Minute"},
2881     {  93, "Degrees Fahrenheit Per Hour"},
2882     {  94, "Degrees Fahrenheit Per Minute"},
2883     {  95, "No Units"},
2884     {  96, "Parts Per Million"},
2885     {  97, "Parts Per Billion"},
2886     {  98, "Percent"},
2887     {  99, "Pecent Per Second"},
2888     { 100, "Per Minute"},
2889     { 101, "Per Second"},
2890     { 102, "Psi Per Degree Fahrenheit"},
2891     { 103, "Radians"},
2892     { 104, "Revolutions Per Min"},
2893     { 105, "Currency1"},
2894     { 106, "Currency2"},
2895     { 107, "Currency3"},
2896     { 108, "Currency4"},
2897     { 109, "Currency5"},
2898     { 110, "Currency6"},
2899     { 111, "Currency7"},
2900     { 112, "Currency8"},
2901     { 113, "Currency9"},
2902     { 114, "Currency10"},
2903     { 115, "Sq Inches"},
2904     { 116, "Sq Centimeters"},
2905     { 117, "BTUs Per Pound"},
2906     { 118, "Centimeters"},
2907     { 119, "Pounds Mass Per Second"},
2908     { 120, "Delta Degrees Fahrenheit"},
2909     { 121, "Delta Degrees Kelvin"},
2910     { 122, "Kilohms"},
2911     { 123, "Megohms"},
2912     { 124, "Millivolts"},
2913     { 125, "Kilojoules Per Kg"},
2914     { 126, "Megajoules"},
2915     { 127, "Joules Per Degree Kelvin"},
2916     { 128, "Joules Per Kg Degree Kelvin"},
2917     { 129, "Kilohertz"},
2918     { 130, "Megahertz"},
2919     { 131, "Per Hour"},
2920     { 132, "Milliwatts"},
2921     { 133, "Hectopascals"},
2922     { 134, "Millibars"},
2923     { 135, "Cubic Meters Per Hour"},
2924     { 136, "Liters Per Hour"},
2925     { 137, "KWatt Hours Per Square Meter"},
2926     { 138, "KWatt Hours Per Square Foot"},
2927     { 139, "Megajoules Per Square Meter"},
2928     { 140, "Megajoules Per Square Foot"},
2929     { 141, "Watts Per Sq Meter Degree Kelvin"},
2930     { 142, "Cubic Feet Per Second"},
2931     { 143, "Percent Obstruction Per Foot"},
2932     { 144, "Percent Obstruction Per Meter"},
2933     { 145, "milliohms"},
2934     { 146, "megawatt-hours"},
2935     { 147, "kilo-btus"},
2936     { 148, "mega-btus"},
2937     { 149, "kilojoules-per-kilogram-dry-air"},
2938     { 150, "megajoules-per-kilogram-dry-air"},
2939     { 151, "kilojoules-per-degree-Kelvin"},
2940     { 152, "megajoules-per-degree-Kelvin"},
2941     { 153, "newton"},
2942     { 154, "grams-per-second"},
2943     { 155, "grams-per-minute"},
2944     { 156, "tons-per-hour"},
2945     { 157, "kilo-btus-per-hour"},
2946     { 158, "hundredths-seconds"},
2947     { 159, "milliseconds"},
2948     { 160, "newton-meters"},
2949     { 161, "millimeters-per-second"},
2950     { 162, "millimeters-per-minute"},
2951     { 163, "meters-per-minute"},
2952     { 164, "meters-per-hour"},
2953     { 165, "cubic-meters-per-minute"},
2954     { 166, "meters-per-second-per-second"},
2955     { 167, "amperes-per-meter"},
2956     { 168, "amperes-per-square-meter"},
2957     { 169, "ampere-square-meters"},
2958     { 170, "farads"},
2959     { 171, "henrys"},
2960     { 172, "ohm-meters"},
2961     { 173, "siemens"},
2962     { 174, "siemens-per-meter"},
2963     { 175, "teslas"},
2964     { 176, "volts-per-degree-Kelvin"},
2965     { 177, "volts-per-meter"},
2966     { 178, "webers"},
2967     { 179, "candelas"},
2968     { 180, "candelas-per-square-meter"},
2969     { 181, "degrees-Kelvin-per-hour"},
2970     { 182, "degrees-Kelvin-per-minute"},
2971     { 183, "joule-seconds"},
2972     { 184, "radians-per-second"},
2973     { 185, "square-meters-per-Newton"},
2974     { 186, "kilograms-per-cubic-meter"},
2975     { 187, "newton-seconds"},
2976     { 188, "newtons-per-meter"},
2977     { 189, "watts-per-meter-per-degree-Kelvin"},
2978     { 190, "micro-siemens"},
2979     { 191, "cubic-feet-per-hour"},
2980     { 192, "us-gallons-per-hour"},
2981     { 193, "kilometers"},
2982     { 194, "micrometers"},
2983     { 195, "grams"},
2984     { 196, "milligrams"},
2985     { 197, "milliliters"},
2986     { 198, "milliliters-per-second"},
2987     { 199, "decibels"},
2988     { 200, "decibels-millivolt"},
2989     { 201, "decibels-volt"},
2990     { 202, "millisiemens"},
2991     { 203, "watt-hours-reactive"},
2992     { 204, "kilowatt-hours-reactive"},
2993     { 205, "megawatt-hours-reactive"},
2994     { 206, "millimeters-of-water"},
2995     { 207, "per-mille"},
2996     { 208, "grams-per-gram"},
2997     { 209, "kilograms-per-kilogram"},
2998     { 210, "grams-per-kilogram"},
2999     { 211, "milligrams-per-gram"},
3000     { 212, "milligrams-per-kilogram"},
3001     { 213, "grams-per-milliliter"},
3002     { 214, "grams-per-liter"},
3003     { 215, "milligrams-per-liter"},
3004     { 216, "micrograms-per-liter"},
3005     { 217, "grams-per-cubic-meter"},
3006     { 218, "milligrams-per-cubic-meter"},
3007     { 219, "micrograms-per-cubic-meter"},
3008     { 220, "nanograms-per-cubic-meter"},
3009     { 221, "grams-per-cubic-centimeter"},
3010     { 222, "becquerels"},
3011     { 223, "kilobecquerels"},
3012     { 224, "megabecquerels"},
3013     { 225, "gray"},
3014     { 226, "milligray"},
3015     { 227, "microgray"},
3016     { 228, "sieverts"},
3017     { 229, "millisieverts"},
3018     { 230, "microsieverts"},
3019     { 231, "microsieverts-per-hour"},
3020     { 232, "decibels-a"},
3021     { 233, "nephelometric-turbidity-unit"},
3022     { 234, "pH"},
3023     { 235, "grams-per-square-meter"},
3024     { 236, "minutes-per-degree-kelvin"},
3025     { 0,   NULL}
3026 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
3027    Enumerated values 256-65535 may be used by others subject to
3028    the procedures and constraints described in Clause 23. */
3029 };
3030
3031 static const value_string
3032 BACnetErrorCode [] = {
3033     {   0, "other"},
3034     {   1, "authentication-failed"},
3035     {   2, "configuration-in-progress"},
3036     {   3, "device-busy"},
3037     {   4, "dynamic-creation-not-supported"},
3038     {   5, "file-access-denied"},
3039     {   6, "incompatible-security-levels"},
3040     {   7, "inconsistent-parameters"},
3041     {   8, "inconsistent-selection-criterion"},
3042     {   9, "invalid-data-type"},
3043     {  10, "invalid-file-access-method"},
3044     {  11, "invalid-file-start-position"},
3045     {  12, "invalid-operator-name"},
3046     {  13, "invalid-parameter-data-type"},
3047     {  14, "invalid-time-stamp"},
3048     {  15, "key-generation-error"},
3049     {  16, "missing-required-parameter"},
3050     {  17, "no-objects-of-specified-type"},
3051     {  18, "no-space-for-object"},
3052     {  19, "no-space-to-add-list-element"},
3053     {  20, "no-space-to-write-property"},
3054     {  21, "no-vt-sessions-available"},
3055     {  22, "property-is-not-a-list"},
3056     {  23, "object-deletion-not-permitted"},
3057     {  24, "object-identifier-already-exists"},
3058     {  25, "operational-problem"},
3059     {  26, "password-failure"},
3060     {  27, "read-access-denied"},
3061     {  28, "security-not-supported"},
3062     {  29, "service-request-denied"},
3063     {  30, "timeout"},
3064     {  31, "unknown-object"},
3065     {  32, "unknown-property"},
3066     {  33, "removed enumeration"},
3067     {  34, "unknown-vt-class"},
3068     {  35, "unknown-vt-session"},
3069     {  36, "unsupported-object-type"},
3070     {  37, "value-out-of-range"},
3071     {  38, "vt-session-already-closed"},
3072     {  39, "vt-session-termination-failure"},
3073     {  40, "write-access-denied"},
3074     {  41, "character-set-not-supported"},
3075     {  42, "invalid-array-index"},
3076     {  43, "cov-subscription-failed"},
3077     {  44, "not-cov-property"},
3078     {  45, "optional-functionality-not-supported"},
3079     {  46, "invalid-configuration-data"},
3080     {  47, "datatype-not-supported"},
3081     {  48, "duplicate-name"},
3082     {  49, "duplicate-object-id"},
3083     {  50, "property-is-not-an-array"},
3084     {  73, "invalid-event-state"},
3085     {  74, "no-alarm-configured"},
3086     {  75, "log-buffer-full"},
3087     {  76, "logged-value-purged"},
3088     {  77, "no-property-specified"},
3089     {  78, "not-configured-for-triggered-logging"},
3090     {  79, "unknown-subscription"},
3091     {  80, "parameter-out-of-range"},
3092     {  81, "list-element-not-found"},
3093     {  82, "busy"},
3094     {  83, "communication-disabled"},
3095     {  84, "success"},
3096     {  85, "access-denied"},
3097     {  86, "bad-destination-address"},
3098     {  87, "bad-destination-device-id"},
3099     {  88, "bad-signature"},
3100     {  89, "bad-source-address"},
3101     {  90, "bad-timestamp"},
3102     {  91, "cannot-use-key"},
3103     {  92, "cannot-verify-message-id"},
3104     {  93, "correct-key-revision"},
3105     {  94, "destination-device-id-required"},
3106     {  95, "duplicate-message"},
3107     {  96, "encryption-not-configured"},
3108     {  97, "encryption-required"},
3109     {  98, "incorrect-key"},
3110     {  99, "invalid-key-data"},
3111     { 100, "key-update-in-progress"},
3112     { 101, "malformed-message"},
3113     { 102, "not-key-server"},
3114     { 103, "security-not-configured"},
3115     { 104, "source-security-required"},
3116     { 105, "too-many-keys"},
3117     { 106, "unknown-authentication-type"},
3118     { 107, "unknown-key"},
3119     { 108, "unknown-key-revision"},
3120     { 109, "unknown-source-message"},
3121     { 110, "not-router-to-dnet"},
3122     { 111, "router-busy"},
3123     { 112, "unknown-network-message"},
3124     { 113, "message-too-long"},
3125     { 114, "security-error"},
3126     { 115, "addressing-error"},
3127     { 116, "write-bdt-failed"},
3128     { 117, "read-bdt-failed"},
3129     { 118, "register-foreign-device-failed"},
3130     { 119, "read-fdt-failed"},
3131     { 120, "delete-fdt-entry-failed"},
3132     { 121, "distribute-broadcast-failed"},
3133     { 122, "unknown-file-size"},
3134     { 123, "abort-apdu-too-long"},
3135     { 124, "abort-application-exceeded-reply-time"},
3136     { 125, "abort-out-of-resources"},
3137     { 126, "abort-tsm-timeout"},
3138     { 127, "abort-window-size-out-of-range"},
3139     { 128, "file-full"},
3140     { 129, "inconsistent-configuration"},
3141     { 130, "inconsistent-object-type"},
3142     { 131, "internal-error"},
3143     { 132, "not-configured"},
3144     { 133, "out-of-memory"},
3145     { 134, "value-too-long"},
3146     { 135, "abort-insufficient-security"},
3147     { 136, "abort-security-error"},
3148     { 0,   NULL}
3149 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
3150    Enumerated values 256-65535 may be used by others subject to the
3151    procedures and constraints described in Clause 23. */
3152 };
3153
3154 static const value_string
3155 BACnetPropertyIdentifier [] = {
3156     {   0, "acked-transition"},
3157     {   1, "ack-required"},
3158     {   2, "action"},
3159     {   3, "action-text"},
3160     {   4, "active-text"},
3161     {   5, "active-vt-session"},
3162     {   6, "alarm-value"},
3163     {   7, "alarm-values"},
3164     {   8, "all"},
3165     {   9, "all-writes-successful"},
3166     {  10, "apdu-segment-timeout"},
3167     {  11, "apdu-timeout"},
3168     {  12, "application-software-version"},
3169     {  13, "archive"},
3170     {  14, "bias"},
3171     {  15, "change-of-state-count"},
3172     {  16, "change-of-state-time"},
3173     {  17, "notification-class"},
3174     {  18, "the property in this place was deleted"},
3175     {  19, "controlled-variable-reference"},
3176     {  20, "controlled-variable-units"},
3177     {  21, "controlled-variable-value"},
3178     {  22, "cov-increment"},
3179     {  23, "datelist"},
3180     {  24, "daylights-savings-status"},
3181     {  25, "deadband"},
3182     {  26, "derivative-constant"},
3183     {  27, "derivative-constant-units"},
3184     {  28, "description"},
3185     {  29, "description-of-halt"},
3186     {  30, "device-address-binding"},
3187     {  31, "device-type"},
3188     {  32, "effective-period"},
3189     {  33, "elapsed-active-time"},
3190     {  34, "error-limit"},
3191     {  35, "event-enable"},
3192     {  36, "event-state"},
3193     {  37, "event-type"},
3194     {  38, "exception-schedule"},
3195     {  39, "fault-values"},
3196     {  40, "feedback-value"},
3197     {  41, "file-access-method"},
3198     {  42, "file-size"},
3199     {  43, "file-type"},
3200     {  44, "firmware-revision"},
3201     {  45, "high-limit"},
3202     {  46, "inactive-text"},
3203     {  47, "in-process"},
3204     {  48, "instance-of"},
3205     {  49, "integral-constant"},
3206     {  50, "integral-constant-units"},
3207     {  51, "issue-confirmed-notifications"},
3208     {  52, "limit-enable"},
3209     {  53, "list-of-group-members"},
3210     {  54, "list-of-object-property-references"},
3211     {  55, "list-of-session-keys"},
3212     {  56, "local-date"},
3213     {  57, "local-time"},
3214     {  58, "location"},
3215     {  59, "low-limit"},
3216     {  60, "manipulated-variable-reference"},
3217     {  61, "maximum-output"},
3218     {  62, "max-apdu-length-accepted"},
3219     {  63, "max-info-frames"},
3220     {  64, "max-master"},
3221     {  65, "max-pres-value"},
3222     {  66, "minimum-off-time"},
3223     {  67, "minimum-on-time"},
3224     {  68, "minimum-output"},
3225     {  69, "min-pres-value"},
3226     {  70, "model-name"},
3227     {  71, "modification-date"},
3228     {  72, "notify-type"},
3229     {  73, "number-of-APDU-retries"},
3230     {  74, "number-of-states"},
3231     {  75, "object-identifier"},
3232     {  76, "object-list"},
3233     {  77, "object-name"},
3234     {  78, "object-property-reference"},
3235     {  79, "object-type"},
3236     {  80, "optional"},
3237     {  81, "out-of-service"},
3238     {  82, "output-units"},
3239     {  83, "event-parameters"},
3240     {  84, "polarity"},
3241     {  85, "present-value"},
3242     {  86, "priority"},
3243     {  87, "priority-array"},
3244     {  88, "priority-for-writing"},
3245     {  89, "process-identifier"},
3246     {  90, "program-change"},
3247     {  91, "program-location"},
3248     {  92, "program-state"},
3249     {  93, "proportional-constant"},
3250     {  94, "proportional-constant-units"},
3251     {  95, "protocol-conformance-class"},
3252     {  96, "protocol-object-types-supported"},
3253     {  97, "protocol-services-supported"},
3254     {  98, "protocol-version"},
3255     {  99, "read-only"},
3256     { 100, "reason-for-halt"},
3257     { 101, "recipient"},
3258     { 102, "recipient-list"},
3259     { 103, "reliability"},
3260     { 104, "relinquish-default"},
3261     { 105, "required"},
3262     { 106, "resolution"},
3263     { 107, "segmentation-supported"},
3264     { 108, "setpoint"},
3265     { 109, "setpoint-reference"},
3266     { 110, "state-text"},
3267     { 111, "status-flags"},
3268     { 112, "system-status"},
3269     { 113, "time-delay"},
3270     { 114, "time-of-active-time-reset"},
3271     { 115, "time-of-state-count-reset"},
3272     { 116, "time-synchronization-recipients"},
3273     { 117, "units"},
3274     { 118, "update-interval"},
3275     { 119, "utc-offset"},
3276     { 120, "vendor-identifier"},
3277     { 121, "vendor-name"},
3278     { 122, "vt-class-supported"},
3279     { 123, "weekly-schedule"},
3280     { 124, "attempted-samples"},
3281     { 125, "average-value"},
3282     { 126, "buffer-size"},
3283     { 127, "client-cov-increment"},
3284     { 128, "cov-resubscription-interval"},
3285     { 129, "current-notify-time"},
3286     { 130, "event-time-stamp"},
3287     { 131, "log-buffer"},
3288     { 132, "log-device-object-property"},
3289     { 133, "enable"}, /* per ANSI/ASHRAE 135-2004 addendum B */
3290     { 134, "log-interval"},
3291     { 135, "maximum-value"},
3292     { 136, "minimum-value"},
3293     { 137, "notification-threshold"},
3294     { 138, "previous-notify-time"},
3295     { 139, "protocol-revision"},
3296     { 140, "records-since-notification"},
3297     { 141, "record-count"},
3298     { 142, "start-time"},
3299     { 143, "stop-time"},
3300     { 144, "stop-when-full"},
3301     { 145, "total-record-count"},
3302     { 146, "valid-samples"},
3303     { 147, "window-interval"},
3304     { 148, "window-samples"},
3305     { 149, "maximum-value-time-stamp"},
3306     { 150, "minimum-value-time-stamp"},
3307     { 151, "variance-value"},
3308     { 152, "active-cov-subscriptions"},
3309     { 153, "backup-failure-timeout"},
3310     { 154, "configuration-files"},
3311     { 155, "database-revision"},
3312     { 156, "direct-reading"},
3313     { 157, "last-restore-time"},
3314     { 158, "maintenance-required"},
3315     { 159, "member-of"},
3316     { 160, "mode"},
3317     { 161, "operation-expected"},
3318     { 162, "setting"},
3319     { 163, "silenced"},
3320     { 164, "tracking-value"},
3321     { 165, "zone-members"},
3322     { 166, "life-safety-alarm-values"},
3323     { 167, "max-segments-accepted"},
3324     { 168, "profile-name"},
3325     { 169, "auto-slave-discovery"},
3326     { 170, "manual-slave-address-binding"},
3327     { 171, "slave-address-binding"},
3328     { 172, "slave-proxy-enable"},
3329     { 173, "last-notify-record"},     /* bug 4117 */
3330     { 174, "schedule-default"},
3331     { 175, "accepted-modes"},
3332     { 176, "adjust-value"},
3333     { 177, "count"},
3334     { 178, "count-before-change"},
3335     { 179, "count-change-time"},
3336     { 180, "cov-period"},
3337     { 181, "input-reference"},
3338     { 182, "limit-monitoring-interval"},
3339     { 183, "logging-device"},
3340     { 184, "logging-record"},
3341     { 185, "prescale"},
3342     { 186, "pulse-rate"},
3343     { 187, "scale"},
3344     { 188, "scale-factor"},
3345     { 189, "update-time"},
3346     { 190, "value-before-change"},
3347     { 191, "value-set"},
3348     { 192, "value-change-time"},
3349     { 193, "align-intervals"},
3350     { 194, "group-member-names"},
3351     { 195, "interval-offset"},
3352     { 196, "last-restart-reason"},
3353     { 197, "logging-type"},
3354     { 198, "member-status-flags"},
3355     { 199, "notification-period"},
3356     { 200, "previous-notify-record"},
3357     { 201, "requested-update-interval"},
3358     { 202, "restart-notification-recipients"},
3359     { 203, "time-of-device-restart"},
3360     { 204, "time-synchronization-interval"},
3361     { 205, "trigger"},
3362     { 206, "UTC-time-synchronization-recipients"},
3363     { 207, "node-subtype"},
3364     { 208, "node-type"},
3365     { 209, "structured-object-list"},
3366     { 210, "subordinate-annotations"},
3367     { 211, "subordinate-list"},
3368     { 212, "actual-shed-level"},
3369     { 213, "duty-window"},
3370     { 214, "expected-shed-level"},
3371     { 215, "full-duty-baseline"},
3372     { 216, "node-subtype"},
3373     { 217, "node-type"},
3374     { 218, "requested-shed-level"},
3375     { 219, "shed-duration"},
3376     { 220, "shed-level-descriptions"},
3377     { 221, "shed-levels"},
3378     { 222, "state-description"},
3379     /* enumeration values 223-225 are unassigned */
3380     { 226, "door-alarm-state"},
3381     { 227, "door-extended-pulse-time"},
3382     { 228, "door-members"},
3383     { 229, "door-open-too-long-time"},
3384     { 230, "door-pulse-time"},
3385     { 231, "door-status"},
3386     { 232, "door-unlock-delay-time"},
3387     { 233, "lock-status"},
3388     { 234, "masked-alarm-values"},
3389     { 235, "secured-status"},
3390     /* enumeration values 236-243 are unassigned */
3391     { 244, "absentee-limit"},     /* added with addenda 135-2008j */
3392     { 245, "access-alarm-events"},
3393     { 246, "access-doors"},
3394     { 247, "access-event"},
3395     { 248, "access-event-authentication-factor"},
3396     { 249, "access-event-credential"},
3397     { 250, "access-event-time"},
3398     { 251, "access-transaction-events"},
3399     { 252, "accompaniment"},
3400     { 253, "accompaniment-time"},
3401     { 254, "activation-time"},
3402     { 255, "active-authentication-policy"},
3403     { 256, "assigned-access-rights"},
3404     { 257, "authentication-factors"},
3405     { 258, "authentication-policy-list"},
3406     { 259, "authentication-policy-names"},
3407     { 260, "authentication-status"},
3408     { 261, "authorization-mode"},
3409     { 262, "belongs-to"},
3410     { 263, "credential-disable"},
3411     { 264, "credential-status"},
3412     { 265, "credentials"},
3413     { 266, "credentials-in-zone"},
3414     { 267, "days-remaining"},
3415     { 268, "entry-points"},
3416     { 269, "exit-points"},
3417     { 270, "expiry-time"},
3418     { 271, "extended-time-enable"},
3419     { 272, "failed-attempt-events"},
3420     { 273, "failed-attempts"},
3421     { 274, "failed-attempts-time"},
3422     { 275, "last-access-event"},
3423     { 276, "last-access-point"},
3424     { 277, "last-credential-added"},
3425     { 278, "last-credential-added-time"},
3426     { 279, "last-credential-removed"},
3427     { 280, "last-credential-removed-time"},
3428     { 281, "last-use-time"},
3429     { 282, "lockout"},
3430     { 283, "lockout-relinquish-time"},
3431     { 284, "master-exemption"},
3432     { 285, "max-failed-attempts"},
3433     { 286, "members"},
3434     { 287, "muster-point"},
3435     { 288, "negative-access-rules"},
3436     { 289, "number-of-authentication-policies"},
3437     { 290, "occupancy-count"},
3438     { 291, "occupancy-count-adjust"},
3439     { 292, "occupancy-count-enable"},
3440     { 293, "occupancy-exemption"},
3441     { 294, "occupancy-lower-limit"},
3442     { 295, "occupancy-lower-limit-enforced"},
3443     { 296, "occupancy-state"},
3444     { 297, "occupancy-upper-limit"},
3445     { 298, "occupancy-upper-limit-enforced"},
3446     { 299, "passback-exemption"},
3447     { 300, "passback-mode"},
3448     { 301, "passback-timeout"},
3449     { 302, "positive-access-rules"},
3450     { 303, "reason-for-disable"},
3451     { 304, "supported-formats"},
3452     { 305, "supported-format-classes"},
3453     { 306, "threat-authority"},
3454     { 307, "threat-level"},
3455     { 308, "trace-flag"},
3456     { 309, "transaction-notification-class"},
3457     { 310, "user-external-identifier"},
3458     { 311, "user-information-reference"},
3459     /* enumeration values 312-316 are unassigned */
3460     { 317, "user-name"},
3461     { 318, "user-type"},
3462     { 319, "uses-remaining"},
3463     { 320, "zone-from"},
3464     { 321, "zone-to"},
3465     { 322, "access-event-tag"},
3466     { 323, "global-identifier"},
3467     /* enumeration values 324-325 reserved for future addenda */
3468     { 326, "verification-time"},
3469     { 327, "base-device-security-policy"},
3470     { 328, "distribution-key-revision"},
3471     { 329, "do-not-hide"},
3472     { 330, "key-sets"},
3473     { 331, "last-key-server"},
3474     { 332, "network-access-security-policies"},
3475     { 333, "packet-reorder-time"},
3476     { 334, "security-pdu-timeout"},
3477     { 335, "security-time-window"},
3478     { 336, "supported-security-algorithms"},
3479     { 337, "update-key-set-timeout"},
3480     { 338, "backup-and-restore-state"},
3481     { 339, "backup-preparation-time"},
3482     { 340, "restore-completion-time"},
3483     { 341, "restore-preparation-time"},
3484     { 342, "bit-mask"},       /* addenda 135-2008w */
3485     { 343, "bit-text"},
3486     { 344, "is-utc"},
3487     { 345, "group-members"},
3488     { 346, "group-member-names"},
3489     { 347, "member-status-flags"},
3490     { 348, "requested-update-interval"},
3491     { 349, "covu-period"},
3492     { 350, "covu-recipients"},
3493     { 351, "event-message-texts"},
3494     { 0,   NULL}
3495 /* Enumerated values 0-511 are reserved for definition by ASHRAE.
3496    Enumerated values 512-4194303 may be used by others subject to
3497    the procedures and constraints described in Clause 23. */
3498 };
3499
3500 static const value_string
3501 BACnetBinaryPV [] = {
3502     { 0, "inactive"},
3503     { 1, "active"},
3504     { 0, NULL}
3505 };
3506
3507
3508 #define ANSI_X3_4      0 /* ANSI X3.4, a/k/a "ASCII"; full UTF-8 since 2010 */
3509                          /* See, for example, ANSI/ASHRAE Addendum k to ANSI/ASHRAE Standard 135-2008 */
3510                          /* XXX - I've seen captures using this for ISO 8859-1 */
3511 #define IBM_MS_DBCS    1 /* "IBM/Microsoft DBCS"; was there only one such DBCS? */
3512 #define JIS_C_6226     2 /* JIS C 6226 */
3513 #define ISO_10646_UCS4 3 /* ISO 10646 (UCS-4) - 4-byte Unicode */
3514 #define ISO_10646_UCS2 4 /* ISO 10646 (UCS-2) - 2-byte Unicode Basic Multilingual Plane (not UTF-16, presumably) */
3515 #define ISO_8859_1     5 /* ISO 8859-1 */
3516 static const value_string
3517 BACnetCharacterSet [] = {
3518     { ANSI_X3_4,      "ANSI X3.4 / UTF-8 (since 2010)"},
3519     { IBM_MS_DBCS,    "IBM/Microsoft DBCS"},
3520     { JIS_C_6226,     "JIS C 6226"},
3521     { ISO_10646_UCS4, "ISO 10646 (UCS-4)"},
3522     { ISO_10646_UCS2, "ISO 10646 (UCS-2)"},
3523     { ISO_8859_1,     "ISO 8859-1"},
3524     { 0,     NULL}
3525 };
3526
3527 static const value_string
3528 BACnetStatusFlags [] = {
3529     { 0, "in-alarm"},
3530     { 1, "fault"},
3531     { 2, "overridden"},
3532     { 3, "out-of-service"},
3533     { 0, NULL}
3534 };
3535
3536 static const value_string
3537 BACnetMessagePriority [] = {
3538     { 0, "normal"},
3539     { 1, "urgent"},
3540     { 0, NULL}
3541 };
3542
3543 static const value_string
3544 BACnetAcknowledgementFilter [] = {
3545     { 0, "all"},
3546     { 1, "acked"},
3547     { 2, "not-acked"},
3548     { 0, NULL}
3549 };
3550
3551 static const value_string
3552 BACnetResultFlags [] = {
3553     { 0, "firstitem"},
3554     { 1, "lastitem"},
3555     { 2, "moreitems"},
3556     { 0, NULL}
3557 };
3558
3559 static const value_string
3560 BACnetRelationSpecifier [] = {
3561     { 0, "equal"},
3562     { 1, "not-equal"},
3563     { 2, "less-than"},
3564     { 3, "greater-than"},
3565     { 4, "less-than-or-equal"},
3566     { 5, "greater-than-or-equal"},
3567     { 0, NULL}
3568 };
3569
3570 static const value_string
3571 BACnetSelectionLogic [] = {
3572     { 0, "and"},
3573     { 1, "or"},
3574     { 2, "all"},
3575     { 0, NULL}
3576 };
3577
3578 static const value_string
3579 BACnetEventStateFilter [] = {
3580     { 0, "offnormal"},
3581     { 1, "fault"},
3582     { 2, "normal"},
3583     { 3, "all"},
3584     { 4, "active"},
3585     { 0, NULL}
3586 };
3587
3588 static const value_string
3589 BACnetEventTransitionBits [] = {
3590     { 0, "to-offnormal"},
3591     { 1, "to-fault"},
3592     { 2, "to-normal"},
3593     { 0, NULL}
3594 };
3595
3596 static const value_string
3597 BACnetSegmentation [] = {
3598     { 0, "segmented-both"},
3599     { 1, "segmented-transmit"},
3600     { 2, "segmented-receive"},
3601     { 3, "no-segmentation"},
3602     { 0, NULL}
3603 };
3604
3605 static const value_string
3606 BACnetSilencedState [] = {
3607     { 0, "unsilenced"},
3608     { 1, "audible-silenced"},
3609     { 2, "visible-silenced"},
3610     { 3, "all-silenced"},
3611     { 0, NULL}
3612 };
3613
3614 static const value_string
3615 BACnetDeviceStatus [] = {
3616     { 0, "operational"},
3617     { 1, "operational-read-only"},
3618     { 2, "download-required"},
3619     { 3, "download-in-progress"},
3620     { 4, "non-operational"},
3621     { 5, "backup-in-progress"},
3622     { 0, NULL}
3623 };
3624
3625 static const value_string
3626 BACnetEnableDisable [] = {
3627     { 0, "enable"},
3628     { 1, "disable"},
3629     { 2, "disable-initiation"},
3630     { 0, NULL}
3631 };
3632
3633 static const value_string
3634 months [] = {
3635     {   1, "January" },
3636     {   2, "February" },
3637     {   3, "March" },
3638     {   4, "April" },
3639     {   5, "May" },
3640     {   6, "June" },
3641     {   7, "July" },
3642     {   8, "August" },
3643     {   9, "September" },
3644     {  10, "October" },
3645     {  11, "November" },
3646     {  12, "December" },
3647     { 255, "any month" },
3648     { 0,   NULL }
3649 };
3650
3651 static const value_string
3652 weekofmonth [] = {
3653     {   1, "days numbered 1-7" },
3654     {   2, "days numbered 8-14" },
3655     {   3, "days numbered 15-21" },
3656     {   4, "days numbered 22-28" },
3657     {   5, "days numbered 29-31" },
3658     {   6, "last 7 days of this month" },
3659     { 255, "any week of this month" },
3660     { 0,   NULL }
3661 };
3662
3663 /* note: notification class object recipient-list uses
3664    different day-of-week enum */
3665 static const value_string
3666 day_of_week [] = {
3667     {   1, "Monday" },
3668     {   2, "Tuesday" },
3669     {   3, "Wednesday" },
3670     {   4, "Thursday" },
3671     {   5, "Friday" },
3672     {   6, "Saturday" },
3673     {   7, "Sunday" },
3674     { 255, "any day of week" },
3675     { 0,   NULL }
3676 };
3677
3678 static const value_string
3679 BACnetErrorClass [] = {
3680     { 0, "device" },
3681     { 1, "object" },
3682     { 2, "property" },
3683     { 3, "resources" },
3684     { 4, "security" },
3685     { 5, "services" },
3686     { 6, "vt" },
3687     { 7, "communication" },
3688     { 0, NULL }
3689 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3690    Enumerated values64-65535 may be used by others subject to
3691    the procedures and constraints described in Clause 23. */
3692 };
3693
3694 static const value_string
3695 BACnetVTClass [] = {
3696     { 0, "default-terminal" },
3697     { 1, "ansi-x3-64" },
3698     { 2, "dec-vt52" },
3699     { 3, "dec-vt100" },
3700     { 4, "dec-vt200" },
3701     { 5, "hp-700-94" },
3702     { 6, "ibm-3130" },
3703     { 0, NULL }
3704 };
3705
3706 static const value_string
3707 BACnetEventType [] = {
3708     {  0, "change-of-bitstring" },
3709     {  1, "change-of-state" },
3710     {  2, "change-of-value" },
3711     {  3, "command-failure" },
3712     {  4, "floating-limit" },
3713     {  5, "out-of-range" },
3714     {  6, "complex-event-type" },
3715     {  7, "(deprecated)buffer-ready" },
3716     {  8, "change-of-life-safety" },
3717     {  9, "extended" },
3718     { 10, "buffer-ready" },
3719     { 11, "unsigned-range" },
3720     { 14, "double-out-of-range"},     /* added with addenda 135-2008w */
3721     { 15, "signed-out-of-range"},
3722     { 16, "unsigned-out-of-range"},
3723     { 17, "change-of-characterstring"},
3724     { 18, "change-of-status-flags"},
3725     { 0,  NULL }
3726 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3727    Enumerated values 64-65535 may be used by others subject to
3728    the procedures and constraints described in Clause 23.
3729    It is expected that these enumerated values will correspond
3730    to the use of the complex-event-type CHOICE [6] of the
3731    BACnetNotificationParameters production. */
3732 };
3733
3734 static const value_string
3735 BACnetEventState [] = {
3736     { 0, "normal" },
3737     { 1, "fault" },
3738     { 2, "offnormal" },
3739     { 3, "high-limit" },
3740     { 4, "low-limit" },
3741     { 5, "life-safety-alarm" },
3742     { 0, NULL }
3743 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3744    Enumerated values 64-65535 may be used by others subject to
3745    the procedures and constraints described in Clause 23.  */
3746 };
3747
3748 static const value_string
3749 BACnetLogStatus [] = {
3750     { 0, "log-disabled" },
3751     { 1, "buffer-purged" },
3752     { 2, "log-interrupted"},
3753     { 0, NULL }
3754 };
3755
3756 static const value_string
3757 BACnetMaintenance [] = {
3758     { 0, "none" },
3759     { 1, "periodic-test" },
3760     { 2, "need-service-operational" },
3761     { 3, "need-service-inoperative" },
3762     { 0, NULL }
3763 };
3764
3765 static const value_string
3766 BACnetNotifyType [] = {
3767     { 0, "alarm" },
3768     { 1, "event" },
3769     { 2, "ack-notification" },
3770     { 0, NULL }
3771 };
3772
3773 static const value_string
3774 BACnetServicesSupported [] = {
3775     {  0, "acknowledgeAlarm"},
3776     {  1, "confirmedCOVNotification"},
3777     {  2, "confirmedEventNotification"},
3778     {  3, "getAlarmSummary"},
3779     {  4, "getEnrollmentSummary"},
3780     {  5, "subscribeCOV"},
3781     {  6, "atomicReadFile"},
3782     {  7, "atomicWriteFile"},
3783     {  8, "addListElement"},
3784     {  9, "removeListElement"},
3785     { 10, "createObject"},
3786     { 11, "deleteObject"},
3787     { 12, "readProperty"},
3788     { 13, "readPropertyConditional"},
3789     { 14, "readPropertyMultiple"},
3790     { 15, "writeProperty"},
3791     { 16, "writePropertyMultiple"},
3792     { 17, "deviceCommunicationControl"},
3793     { 18, "confirmedPrivateTransfer"},
3794     { 19, "confirmedTextMessage"},
3795     { 20, "reinitializeDevice"},
3796     { 21, "vtOpen"},
3797     { 22, "vtClose"},
3798     { 23, "vtData"},
3799     { 24, "authenticate"},
3800     { 25, "requestKey"},
3801     { 26, "i-Am"},
3802     { 27, "i-Have"},
3803     { 28, "unconfirmedCOVNotification"},
3804     { 29, "unconfirmedEventNotification"},
3805     { 30, "unconfirmedPrivateTransfer"},
3806     { 31, "unconfirmedTextMessage"},
3807     { 32, "timeSynchronization"},
3808     { 33, "who-Has"},
3809     { 34, "who-Is"},
3810     { 35, "readRange"},
3811     { 36, "utcTimeSynchronization"},
3812     { 37, "lifeSafetyOperation"},
3813     { 38, "subscribeCOVProperty"},
3814     { 39, "getEventInformation"},
3815     { 0,  NULL}
3816 };
3817
3818 static const value_string
3819 BACnetPropertyStates [] = {
3820     {  0, "boolean-value"},
3821     {  1, "binary-value"},
3822     {  2, "event-type"},
3823     {  3, "polarity"},
3824     {  4, "program-change"},
3825     {  5, "program-state"},
3826     {  6, "reason-for-halt"},
3827     {  7, "reliability"},
3828     {  8, "state"},
3829     {  9, "system-status"},
3830     { 10, "units"},
3831     { 11, "unsigned-value"},
3832     { 12, "life-safety-mode"},
3833     { 13, "life-safety-state"},
3834     { 14, "restart-reason"},
3835     { 15, "door-alarm-state"},
3836     { 16, "action"},
3837     { 17, "door-secured-status"},
3838     { 18, "door-status"},
3839     { 19, "door-value"},
3840     { 20, "file-access-method"},
3841     { 21, "lock-status"},
3842     { 22, "life-safety-operation"},
3843     { 23, "maintenance"},
3844     { 24, "node-type"},
3845     { 25, "notify-type"},
3846     { 26, "security-level"},
3847     { 27, "shed-state"},
3848     { 28, "silenced-state"},
3849     /* context tag 29 reserved for future addenda */
3850     { 29, "unknown-29"},
3851     { 30, "access-event"},
3852     { 31, "zone-occupancy-state"},
3853     { 32, "access-credential-disable-reason"},
3854     { 33, "access-credential-disable"},
3855     { 34, "authentication-status"},
3856     { 35, "unknown-35"},
3857     { 36, "backup-state"},
3858     { 0, NULL}
3859 /* Tag values 0-63 are reserved for definition by ASHRAE.
3860    Tag values of 64-254 may be used by others to accommodate
3861    vendor specific properties that have discrete or enumerated values,
3862    subject to the constraints described in Clause 23. */
3863 };
3864
3865 static const value_string
3866 BACnetProgramError [] = {
3867     { 0, "normal"},
3868     { 1, "load-failed"},
3869     { 2, "internal"},
3870     { 3, "program"},
3871     { 4, "other"},
3872     { 0, NULL}
3873 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3874    Enumerated values 64-65535 may be used by others subject to
3875    the procedures and constraints described in Clause 23. */
3876 };
3877
3878 static const value_string
3879 BACnetProgramRequest [] = {
3880     { 0, "ready"},
3881     { 1, "load"},
3882     { 2, "run"},
3883     { 3, "halt"},
3884     { 4, "restart"},
3885     { 4, "unload"},
3886     { 0, NULL}
3887 };
3888
3889 static const value_string
3890 BACnetProgramState [] = {
3891     { 0, "idle"},
3892     { 1, "loading"},
3893     { 2, "running"},
3894     { 3, "waiting"},
3895     { 4, "halted"},
3896     { 4, "unloading"},
3897     { 0, NULL}
3898 };
3899
3900 static const value_string
3901 BACnetReinitializedStateOfDevice [] = {
3902     { 0, "coldstart"},
3903     { 1, "warmstart"},
3904     { 2, "startbackup"},
3905     { 3, "endbackup"},
3906     { 4, "startrestore"},
3907     { 5, "endrestore"},
3908     { 6, "abortrestore"},
3909     { 0, NULL}
3910 };
3911
3912 static const value_string
3913 BACnetPolarity [] = {
3914     { 0, "normal"},
3915     { 1, "reverse"},
3916     { 0, NULL}
3917 };
3918
3919 static const value_string
3920 BACnetTagNames[] = {
3921     { 5, "Extended Value" },
3922     { 6, "Opening Tag" },
3923     { 7, "Closing Tag" },
3924     { 0, NULL }
3925 };
3926
3927 static const value_string
3928 BACnetReadRangeOptions[] = {
3929     { 3, "range byPosition" },
3930     { 4, "range byTime" },
3931     { 5, "range timeRange" },
3932     { 6, "range bySequenceNumber" },
3933     { 7, "range byTime" },
3934     { 0, NULL }
3935 };
3936
3937 /* Present_Value for Load Control Object */
3938 static const value_string
3939 BACnetShedState[] = {
3940     { 0, "shed-inactive" },
3941     { 1, "shed-request-pending" },
3942     { 2, "shed-compliant" },
3943     { 3, "shed-non-compliant" },
3944     { 0, NULL }
3945 };
3946
3947 static const value_string
3948 BACnetNodeType [] = {
3949     { 0, "unknown" },
3950     { 1, "system" },
3951     { 2, "network" },
3952     { 3, "device" },
3953     { 4, "organizational" },
3954     { 5, "area" },
3955     { 6, "equipment" },
3956     { 7, "point" },
3957     { 8, "collection" },
3958     { 9, "property" },
3959     { 10, "functional" },
3960     { 11, "other" },
3961     { 0, NULL }
3962 };
3963
3964 static const value_string
3965 BACnetLoggingType [] = {
3966     { 0, "polled" },
3967     { 1, "cov" },
3968     { 2, "triggered" },
3969     { 0, NULL }
3970 };
3971
3972 static const value_string
3973 BACnetDoorStatus [] = {
3974     { 0, "closed" },
3975     { 1, "opened" },
3976     { 2, "unknown" },
3977     { 0, NULL }
3978 };
3979
3980 static const value_string
3981 BACnetLockStatus [] = {
3982     { 0, "locked" },
3983     { 1, "unlocked" },
3984     { 2, "fault" },
3985     { 3, "unknown" },
3986     { 0, NULL }
3987 };
3988
3989 static const value_string
3990 BACnetDoorSecuredStatus [] = {
3991     { 0, "secured" },
3992     { 1, "unsecured" },
3993     { 2, "unknown" },
3994     { 0, NULL }
3995 };
3996
3997 static const value_string
3998 BACnetDoorAlarmState [] = {
3999     { 0, "normal" },
4000     { 1, "alarm" },
4001     { 2, "door-open-too-long" },
4002     { 3, "forced-open" },
4003     { 4, "tamper" },
4004     { 5, "door-fault" },
4005     { 6, "lock-down" },
4006     { 7, "free-access" },
4007     { 8, "egress-open" },
4008     { 0, NULL }
4009 };
4010
4011 static const value_string
4012 BACnetAccumulatorStatus [] = {
4013     { 0, "normal" },
4014     { 1, "starting" },
4015     { 2, "recovered" },
4016     { 3, "abnormal" },
4017     { 4, "failed" },
4018     { 0, NULL }
4019 };
4020
4021 /* These values are (manually) transferred from
4022  * http://www.bacnet.org/VendorID/BACnet Vendor IDs.htm
4023  * Version: "As of September 16, 2013"
4024  */
4025
4026 static const value_string
4027 BACnetVendorIdentifiers [] = {
4028     {   0, "ASHRAE" },
4029     {   1, "NIST" },
4030     {   2, "The Trane Company" },
4031     {   3, "McQuay International" },
4032     {   4, "PolarSoft" },
4033     {   5, "Johnson Controls, Inc." },
4034     {   6, "American Auto-Matrix" },
4035     {   7, "Siemens Schweiz AG (Formerly: Landis & Staefa Division Europe)" },
4036     {   8, "Delta Controls" },
4037     {   9, "Siemens Schweiz AG" },
4038     {  10, "Schneider Electric" },
4039     {  11, "TAC" },
4040     {  12, "Orion Analysis Corporation" },
4041     {  13, "Teletrol Systems Inc." },
4042     {  14, "Cimetrics Technology" },
4043     {  15, "Cornell University" },
4044     {  16, "United Technologies Carrier" },
4045     {  17, "Honeywell Inc." },
4046     {  18, "Alerton / Honeywell" },
4047     {  19, "TAC AB" },
4048     {  20, "Hewlett-Packard Company" },
4049     {  21, "Dorsette's Inc." },
4050     {  22, "Siemens Schweiz AG (Formerly: Cerberus AG)" },
4051     {  23, "York Controls Group" },
4052     {  24, "Automated Logic Corporation" },
4053     {  25, "CSI Control Systems International" },
4054     {  26, "Phoenix Controls Corporation" },
4055     {  27, "Innovex Technologies, Inc." },
4056     {  28, "KMC Controls, Inc." },
4057     {  29, "Xn Technologies, Inc." },
4058     {  30, "Hyundai Information Technology Co., Ltd." },
4059     {  31, "Tokimec Inc." },
4060     {  32, "Simplex" },
4061     {  33, "North Building Technologies Limited" },
4062     {  34, "Notifier" },
4063     {  35, "Reliable Controls Corporation" },
4064     {  36, "Tridium Inc." },
4065     {  37, "Sierra Monitor Corporation/FieldServer Technologies" },
4066     {  38, "Silicon Energy" },
4067     {  39, "Kieback & Peter GmbH & Co KG" },
4068     {  40, "Anacon Systems, Inc." },
4069     {  41, "Systems Controls & Instruments, LLC" },
4070     {  42, "Lithonia Lighting" },
4071     {  43, "Micropower Manufacturing" },
4072     {  44, "Matrix Controls" },
4073     {  45, "METALAIRE" },
4074     {  46, "ESS Engineering" },
4075     {  47, "Sphere Systems Pty Ltd." },
4076     {  48, "Walker Technologies Corporation" },
4077     {  49, "H I Solutions, Inc." },
4078     {  50, "MBS GmbH" },
4079     {  51, "SAMSON AG" },
4080     {  52, "Badger Meter Inc." },
4081     {  53, "DAIKIN Industries Ltd." },
4082     {  54, "NARA Controls Inc." },
4083     {  55, "Mammoth Inc." },
4084     {  56, "Liebert Corporation" },
4085     {  57, "SEMCO Incorporated" },
4086     {  58, "Air Monitor Corporation" },
4087     {  59, "TRIATEK, LLC" },
4088     {  60, "NexLight" },
4089     {  61, "Multistack" },
4090     {  62, "TSI Incorporated" },
4091     {  63, "Weather-Rite, Inc." },
4092     {  64, "Dunham-Bush" },
4093     {  65, "Reliance Electric" },
4094     {  66, "LCS Inc." },
4095     {  67, "Regulator Australia PTY Ltd." },
4096     {  68, "Touch-Plate Lighting Controls" },
4097     {  69, "Amann GmbH" },
4098     {  70, "RLE Technologies" },
4099     {  71, "Cardkey Systems" },
4100     {  72, "SECOM Co., Ltd." },
4101     {  73, "ABB Gebaeudetechnik AG Bereich NetServ" },
4102     {  74, "KNX Association cvba" },
4103     {  75, "Institute of Electrical Installation Engineers of Japan (IEIEJ)" },
4104     {  76, "Nohmi Bosai, Ltd." },
4105     {  77, "Carel S.p.A." },
4106     {  78, "UTC Fire & Security Espana, S.L." },
4107     {  79, "Hochiki Corporation" },
4108     {  80, "Fr. Sauter AG" },
4109     {  81, "Matsushita Electric Works, Ltd." },
4110     {  82, "Mitsubishi Electric Corporation, Inazawa Works" },
4111     {  83, "Mitsubishi Heavy Industries, Ltd." },
4112     {  84, "ITT Bell & Gossett" },
4113     {  85, "Yamatake Building Systems Co., Ltd." },
4114     {  86, "The Watt Stopper, Inc." },
4115     {  87, "Aichi Tokei Denki Co., Ltd." },
4116     {  88, "Activation Technologies, LLC" },
4117     {  89, "Saia-Burgess Controls, Ltd." },
4118     {  90, "Hitachi, Ltd." },
4119     {  91, "Novar Corp./Trend Control Systems Ltd." },
4120     {  92, "Mitsubishi Electric Lighting Corporation" },
4121     {  93, "Argus Control Systems, Ltd." },
4122     {  94, "Kyuki Corporation" },
4123     {  95, "Richards-Zeta Building Intelligence, Inc." },
4124     {  96, "Scientech R&D, Inc." },
4125     {  97, "VCI Controls, Inc." },
4126     {  98, "Toshiba Corporation" },
4127     {  99, "Mitsubishi Electric Corporation Air Conditioning & Refrigeration Systems Works" },
4128     { 100, "Custom Mechanical Equipment, LLC" },
4129     { 101, "ClimateMaster" },
4130     { 102, "ICP Panel-Tec, Inc." },
4131     { 103, "D-Tek Controls" },
4132     { 104, "NEC Engineering, Ltd." },
4133     { 105, "PRIVA BV" },
4134     { 106, "Meidensha Corporation" },
4135     { 107, "JCI Systems Integration Services" },
4136     { 108, "Freedom Corporation" },
4137     { 109, "Neuberger Gebaeudeautomation GmbH" },
4138     { 110, "Sitronix" },
4139     { 111, "Leviton Manufacturing" },
4140     { 112, "Fujitsu Limited" },
4141     { 113, "Emerson Network Power" },
4142     { 114, "S. A. Armstrong, Ltd." },
4143     { 115, "Visonet AG" },
4144     { 116, "M&M Systems, Inc." },
4145     { 117, "Custom Software Engineering" },
4146     { 118, "Nittan Company, Limited" },
4147     { 119, "Elutions Inc. (Wizcon Systems SAS)" },
4148     { 120, "Pacom Systems Pty., Ltd." },
4149     { 121, "Unico, Inc." },
4150     { 122, "Ebtron, Inc." },
4151     { 123, "Scada Engine" },
4152     { 124, "AC Technology Corporation" },
4153     { 125, "Eagle Technology" },
4154     { 126, "Data Aire, Inc." },
4155     { 127, "ABB, Inc." },
4156     { 128, "Transbit Sp. z o. o." },
4157     { 129, "Toshiba Carrier Corporation" },
4158     { 130, "Shenzhen Junzhi Hi-Tech Co., Ltd." },
4159     { 131, "Tokai Soft" },
4160     { 132, "Blue Ridge Technologies" },
4161     { 133, "Veris Industries" },
4162     { 134, "Centaurus Prime" },
4163     { 135, "Sand Network Systems" },
4164     { 136, "Regulvar, Inc." },
4165     { 137, "AFDtek Division of Fastek International Inc." },
4166     { 138, "PowerCold Comfort Air Solutions, Inc." },
4167     { 139, "I Controls" },
4168     { 140, "Viconics Electronics, Inc." },
4169     { 141, "Yaskawa America, Inc." },
4170     { 142, "DEOS control systems GmbH" },
4171     { 143, "Digitale Mess- und Steuersysteme AG" },
4172     { 144, "Fujitsu General Limited" },
4173     { 145, "Project Engineering S.r.l." },
4174     { 146, "Sanyo Electric Co., Ltd." },
4175     { 147, "Integrated Information Systems, Inc." },
4176     { 148, "Temco Controls, Ltd." },
4177     { 149, "Airtek International Inc." },
4178     { 150, "Advantech Corporation" },
4179     { 151, "Titan Products, Ltd." },
4180     { 152, "Regel Partners" },
4181     { 153, "National Environmental Product" },
4182     { 154, "Unitec Corporation" },
4183     { 155, "Kanden Engineering Company" },
4184     { 156, "Messner Gebaeudetechnik GmbH" },
4185     { 157, "Integrated.CH" },
4186     { 158, "Price Industries" },
4187     { 159, "SE-Elektronic GmbH" },
4188     { 160, "Rockwell Automation" },
4189     { 161, "Enflex Corp." },
4190     { 162, "ASI Controls" },
4191     { 163, "SysMik GmbH Dresden" },
4192     { 164, "HSC Regelungstechnik GmbH" },
4193     { 165, "Smart Temp Australia Pty.  Ltd." },
4194     { 166, "Cooper Controls" },
4195     { 167, "Duksan Mecasys Co., Ltd." },
4196     { 168, "Fuji IT Co., Ltd." },
4197     { 169, "Vacon Plc" },
4198     { 170, "Leader Controls" },
4199     { 171, "Cylon Controls, Ltd." },
4200     { 172, "Compas" },
4201     { 173, "Mitsubishi Electric Building Techno-Service Co., Ltd." },
4202     { 174, "Building Control Integrators" },
4203     { 175, "ITG Worldwide (M) Sdn Bhd" },
4204     { 176, "Lutron Electronics Co., Inc." },
4205     { 177, "Cooper-Atkins Corporation" },
4206     { 178, "LOYTEC Electronics GmbH" },
4207     { 179, "ProLon" },
4208     { 180, "Mega Controls Limited" },
4209     { 181, "Micro Control Systems, Inc." },
4210     { 182, "Kiyon, Inc." },
4211     { 183, "Dust Networks" },
4212     { 184, "Advanced Building Automation Systems" },
4213     { 185, "Hermos AG" },
4214     { 186, "CEZIM" },
4215     { 187, "Softing" },
4216     { 188, "Lynxspring, Inc." },
4217     { 189, "Schneider Toshiba Inverter Europe" },
4218     { 190, "Danfoss Drives A/S" },
4219     { 191, "Eaton Corporation" },
4220     { 192, "Matyca S.A." },
4221     { 193, "Botech AB" },
4222     { 194, "Noveo, Inc." },
4223     { 195, "AMEV" },
4224     { 196, "Yokogawa Electric Corporation" },
4225     { 197, "GFR Gesellschaft fuer Regelungstechnik" },
4226     { 198, "Exact Logic" },
4227     { 199, "Mass Electronics Pty Ltd dba Innotech Control Systems Australia" },
4228     { 200, "Kandenko Co., Ltd." },
4229     { 201, "DTF, Daten-Technik Fries" },
4230     { 202, "Klimasoft, Ltd." },
4231     { 203, "Toshiba Schneider Inverter Corporation" },
4232     { 204, "Control Applications, Ltd." },
4233     { 205, "KDT Systems Co., Ltd." },
4234     { 206, "Onicon Incorporated" },
4235     { 207, "Automation Displays, Inc." },
4236     { 208, "Control Solutions, Inc." },
4237     { 209, "Remsdaq Limited" },
4238     { 210, "NTT Facilities, Inc." },
4239     { 211, "VIPA GmbH" },
4240     { 212, "TSC21 Association of Japan" },
4241     { 213, "Strato Automation" },
4242     { 214, "HRW Limited" },
4243     { 215, "Lighting Control & Design, Inc." },
4244     { 216, "Mercy Electronic and Electrical Industries" },
4245     { 217, "Samsung SDS Co., Ltd" },
4246     { 218, "Impact Facility Solutions, Inc." },
4247     { 219, "Aircuity" },
4248     { 220, "Control Techniques, Ltd." },
4249     { 221, "OpenGeneral Pty., Ltd." },
4250     { 222, "WAGO Kontakttechnik GmbH & Co. KG" },
4251     { 223, "Cerus Industrial" },
4252     { 224, "Chloride Power Protection Company" },
4253     { 225, "Computrols, Inc." },
4254     { 226, "Phoenix Contact GmbH & Co. KG" },
4255     { 227, "Grundfos Management A/S" },
4256     { 228, "Ridder Drive Systems" },
4257     { 229, "Soft Device SDN BHD" },
4258     { 230, "Integrated Control Technology Limited" },
4259     { 231, "AIRxpert Systems, Inc." },
4260     { 232, "Microtrol Limited" },
4261     { 233, "Red Lion Controls" },
4262     { 234, "Digital Electronics Corporation" },
4263     { 235, "Ennovatis GmbH" },
4264     { 236, "Serotonin Software Technologies, Inc." },
4265     { 237, "LS Industrial Systems Co., Ltd." },
4266     { 238, "Square D Company" },
4267     { 239, "S Squared Innovations, Inc." },
4268     { 240, "Aricent Ltd." },
4269     { 241, "EtherMetrics, LLC" },
4270     { 242, "Industrial Control Communications, Inc." },
4271     { 243, "Paragon Controls, Inc." },
4272     { 244, "A. O. Smith Corporation" },
4273     { 245, "Contemporary Control Systems, Inc." },
4274     { 246, "Intesis Software SL" },
4275     { 247, "Ingenieurgesellschaft N. Hartleb mbH" },
4276     { 248, "Heat-Timer Corporation" },
4277     { 249, "Ingrasys Technology, Inc." },
4278     { 250, "Costerm Building Automation" },
4279     { 251, "WILO SE" },
4280     { 252, "Embedia Technologies Corp." },
4281     { 253, "Technilog" },
4282     { 254, "HR Controls Ltd. & Co. KG" },
4283     { 255, "Lennox International, Inc." },
4284     { 256, "RK-Tec Rauchklappen-Steuerungssysteme GmbH & Co. KG" },
4285     { 257, "Thermomax, Ltd." },
4286     { 258, "ELCON Electronic Control, Ltd." },
4287     { 259, "Larmia Control AB" },
4288     { 260, "BACnet Stack at SourceForge" },
4289     { 261, "G4S Security Services A/S" },
4290     { 262, "Exor International S.p.A." },
4291     { 263, "Cristal Controles" },
4292     { 264, "Regin AB" },
4293     { 265, "Dimension Software, Inc." },
4294     { 266, "SynapSense Corporation" },
4295     { 267, "Beijing Nantree Electronic Co., Ltd." },
4296     { 268, "Camus Hydronics Ltd." },
4297     { 269, "Kawasaki Heavy Industries, Ltd." },
4298     { 270, "Critical Environment Technologies" },
4299     { 271, "ILSHIN IBS Co., Ltd." },
4300     { 272, "ELESTA Energy Control AG" },
4301     { 273, "KROPMAN Installatietechniek" },
4302     { 274, "Baldor Electric Company" },
4303     { 275, "INGA mbH" },
4304     { 276, "GE Consumer & Industrial" },
4305     { 277, "Functional Devices, Inc." },
4306     { 278, "ESAC" },
4307     { 279, "M-System Co., Ltd." },
4308     { 280, "Yokota Co., Ltd." },
4309     { 281, "Hitranse Technology Co., LTD" },
4310     { 282, "Federspiel Controls" },
4311     { 283, "Kele, Inc." },
4312     { 284, "Opera Electronics, Inc." },
4313     { 285, "Gentec" },
4314     { 286, "Embedded Science Labs, LLC" },
4315     { 287, "Parker Hannifin Corporation" },
4316     { 288, "MaCaPS International Limited" },
4317     { 289, "Link4 Corporation" },
4318     { 290, "Romutec Steuer-u. Regelsysteme GmbH" },
4319     { 291, "Pribusin, Inc." },
4320     { 292, "Advantage Controls" },
4321     { 293, "Critical Room Control" },
4322     { 294, "LEGRAND" },
4323     { 295, "Tongdy Control Technology Co., Ltd." },
4324     { 296, "ISSARO Integrierte Systemtechnik" },
4325     { 297, "Pro-Dev Industries" },
4326     { 298, "DRI-STEEM" },
4327     { 299, "Creative Electronic GmbH" },
4328     { 300, "Swegon AB" },
4329     { 301, "Jan Brachacek" },
4330     { 302, "Hitachi Appliances, Inc." },
4331     { 303, "Real Time Automation, Inc." },
4332     { 304, "ITEC Hankyu-Hanshin Co." },
4333     { 305, "Cyrus E&M Engineering Co., Ltd." },
4334     { 306, "Badger Meter" },
4335     { 307, "Cirrascale Corporation" },
4336     { 308, "Elesta GmbH Building Automation" },
4337     { 309, "Securiton" },
4338     { 310, "OSlsoft, Inc." },
4339     { 311, "Hanazeder Electronic GmbH" },
4340     { 312, "Honeywell Security Deutschland, Novar GmbH" },
4341     { 313, "Siemens Energy & Automation, Inc." },
4342     { 314, "ETM Professional Control GmbH" },
4343     { 315, "Meitav-tec, Ltd." },
4344     { 316, "Janitza Electronics GmbH" },
4345     { 317, "MKS Nordhausen" },
4346     { 318, "De Gier Drive Systems B.V." },
4347     { 319, "Cypress Envirosystems" },
4348     { 320, "SMARTron s.r.o." },
4349     { 321, "Verari Systems, Inc." },
4350     { 322, "K-W Electronic Service, Inc." },
4351     { 323, "ALFA-SMART Energy Management" },
4352     { 324, "Telkonet, Inc." },
4353     { 325, "Securiton GmbH" },
4354     { 326, "Cemtrex, Inc." },
4355     { 327, "Performance Technologies, Inc." },
4356     { 328, "Xtralis (Aust) Pty Ltd" },
4357     { 329, "TROX GmbH" },
4358     { 330, "Beijing Hysine Technology Co., Ltd" },
4359     { 331, "RCK Controls, Inc." },
4360     { 332, "Distech Controls SAS" },
4361     { 333, "Novar/Honeywell" },
4362     { 334, "The S4 Group, Inc." },
4363     { 335, "Schneider Electric" },
4364     { 336, "LHA Systems" },
4365     { 337, "GHM engineering Group, Inc." },
4366     { 338, "Cllimalux S.A." },
4367     { 339, "VAISALA Oyj" },
4368     { 340, "COMPLEX (Beijing) Technology, Co., LTD." },
4369     { 341, "SCADAmetrics" },
4370     { 342, "POWERPEG NSI Limited" },
4371     { 343, "BACnet Interoperability Testing Services, Inc." },
4372     { 344, "Teco a.s." },
4373     { 345, "Plexus Technology, Inc." },
4374     { 346, "Energy Focus, Inc." },
4375     { 347, "Powersmiths International Corp." },
4376     { 348, "Nichibei Co., Ltd." },
4377     { 349, "HKC Technology Ltd." },
4378     { 350, "Ovation Networks, Inc." },
4379     { 351, "Setra Systems" },
4380     { 352, "AVG Automation" },
4381     { 353, "ZXC Ltd." },
4382     { 354, "Byte Sphere" },
4383     { 355, "Generiton Co., Ltd." },
4384     { 356, "Holter Regelarmaturen GmbH & Co. KG" },
4385     { 357, "Bedford Instruments, LLC" },
4386     { 358, "Standair Inc." },
4387     { 359, "WEG Automation - R&D" },
4388     { 360, "Prolon Control Systems ApS" },
4389     { 361, "Inneasoft" },
4390     { 362, "ConneXSoft GmbH" },
4391     { 363, "CEAG Notlichtsysteme GmbH" },
4392     { 364, "Distech Controls Inc." },
4393     { 365, "Industrial Technology Research Institute" },
4394     { 366, "ICONICS, Inc." },
4395     { 367, "IQ Controls s.c." },
4396     { 368, "OJ Electronics A/S" },
4397     { 369, "Rolbit Ltd." },
4398     { 370, "Synapsys Solutions Ltd." },
4399     { 371, "ACME Engineering Prod. Ltd." },
4400     { 372, "Zener Electric Pty, Ltd." },
4401     { 373, "Selectronix, Inc." },
4402     { 374, "Gorbet & Banerjee, LLC." },
4403     { 375, "IME" },
4404     { 376, "Stephen H. Dawson Computer Service" },
4405     { 377, "Accutrol, LLC" },
4406     { 378, "Schneider Elektronik GmbH" },
4407     { 379, "Alpha-Inno Tec GmbH" },
4408     { 380, "ADMMicro, Inc." },
4409     { 381, "Greystone Energy Systems, Inc." },
4410     { 382, "CAP Technologie" },
4411     { 383, "KeRo Systems" },
4412     { 384, "Domat Control System s.r.o." },
4413     { 385, "Efektronics Pty. Ltd." },
4414     { 386, "Hekatron Vertriebs GmbH" },
4415     { 387, "Securiton AG" },
4416     { 388, "Carlo Gavazzi Controls SpA" },
4417     { 389, "Chipkin Automation Systems" },
4418     { 390, "Savant Systems, LLC" },
4419     { 391, "Simmtronic Lighting Controls" },
4420     { 392, "Abelko Innovation AB" },
4421     { 393, "Seresco Technologies Inc." },
4422     { 394, "IT Watchdogs" },
4423     { 395, "Automation Assist Japan Corp." },
4424     { 396, "Thermokon Sensortechnik GmbH" },
4425     { 397, "EGauge Systems, LLC" },
4426     { 398, "Quantum Automation (ASIA) PTE, Ltd." },
4427     { 399, "Toshiba Lighting & Technology Corp." },
4428     { 400, "SPIN Engenharia de Automacao Ltda." },
4429     { 401, "Logistics Systems & Software Services India PVT. Ltd." },
4430     { 402, "Delta Controls Integration Products" },
4431     { 403, "Focus Media" },
4432     { 404, "LUMEnergi Inc." },
4433     { 405, "Kara Systems" },
4434     { 406, "RF Code, Inc." },
4435     { 407, "Fatek Automation Corp." },
4436     { 408, "JANDA Software Company, LLC" },
4437     { 409, "Open System Solutions Limited" },
4438     { 410, "Intelec Systems PTY Ltd." },
4439     { 411, "Ecolodgix, LLC" },
4440     { 412, "Douglas Lighting Controls" },
4441     { 413, "iSAtech GmbH" },
4442     { 414, "AREAL" },
4443     { 415, "Beckhoff Automation GmbH" },
4444     { 416, "IPAS GmbH" },
4445     { 417, "KE2 Therm Solutions" },
4446     { 418, "Base2Products" },
4447     { 419, "DTL Controls, LLC" },
4448     { 420, "INNCOM International, Inc." },
4449     { 421, "BTR Netcom GmbH" },
4450     { 422, "Greentrol Automation, Inc" },
4451     { 423, "BELIMO Automation AG" },
4452     { 424, "Samsung Heavy Industries Co, Ltd" },
4453     { 425, "Triacta Power Technologies, Inc." },
4454     { 426, "Globestar Systems" },
4455     { 427, "MLB Advanced Media, LP" },
4456     { 428, "SWG Stuckmann Wirtschaftliche Gebaeudesysteme GmbH" },
4457     { 429, "SensorSwitch" },
4458     { 430, "Multitek Power Limited" },
4459     { 431, "Aquametro AG" },
4460     { 432, "LG Electronics Inc." },
4461     { 433, "Electronic Theatre Controls, Inc." },
4462     { 434, "Mitsubishi Electric Corporation Nagoya Works" },
4463     { 435, "Delta Electronics, Inc." },
4464     { 436, "Elma Kurtalj, Ltd." },
4465     { 437, "ADT Fire and Security Sp. A.o.o." },
4466     { 438, "Nedap Security Management" },
4467     { 439, "ESC Automation Inc." },
4468     { 440, "DSP4YOU Ltd." },
4469     { 441, "GE Sensing and Inspection Technologies" },
4470     { 442, "Embedded Systems SIA" },
4471     { 443, "BEFEGA GmbH" },
4472     { 444, "Baseline Inc." },
4473     { 445, "M2M Systems Integrators" },
4474     { 446, "OEMCtrl" },
4475     { 447, "Clarkson Controls Limited" },
4476     { 448, "Rogerwell Control System Limited" },
4477     { 449, "SCL Elements" },
4478     { 450, "Hitachi Ltd." },
4479     { 451, "Newron System SA" },
4480     { 452, "BEVECO Gebouwautomatisering BV" },
4481     { 453, "Streamside Solutions" },
4482     { 454, "Yellowstone Soft" },
4483     { 455, "Oztech Intelligent Systems Pty Ltd." },
4484     { 456, "Novelan GmbH" },
4485     { 457, "Flexim Americas Corporation" },
4486     { 458, "ICP DAS Co., Ltd." },
4487     { 459, "CARMA Industries Inc." },
4488     { 460, "Log-One Ltd." },
4489     { 461, "TECO Electric & Machinery Co., Ltd." },
4490     { 462, "ConnectEx, Inc." },
4491     { 463, "Turbo DDC Suedwest" },
4492     { 464, "Quatrosense Environmental Ltd." },
4493     { 465, "Fifth Light Technology Ltd." },
4494     { 466, "Scientific Solutions, Ltd." },
4495     { 467, "Controller Area Network Solutions (M) Sdn Bhd" },
4496     { 468, "RESOL - Elektronische Regelungen GmbH" },
4497     { 469, "RPBUS LLC" },
4498     { 470, "BRS Sistemas Eletronicos" },
4499     { 471, "WindowMaster A/S" },
4500     { 472, "Sunlux Technologies Ltd." },
4501     { 473, "Measurlogic" },
4502     { 474, "Frimat GmbH" },
4503     { 475, "Spirax Sarco" },
4504     { 476, "Luxtron" },
4505     { 477, "Raypak Inc" },
4506     { 478, "Air Monitor Corporation" },
4507     { 479, "Regler Och Webbteknik Sverige (ROWS)" },
4508     { 480, "Intelligent Lighting Controls Inc." },
4509     { 481, "Sanyo Electric Industry Co., Ltd" },
4510     { 482, "E-Mon Energy Monitoring Products" },
4511     { 483, "Digital Control Systems" },
4512     { 484, "ATI Airtest Technologies, Inc." },
4513     { 485, "SCS SA" },
4514     { 486, "HMS Industrial Networks AB" },
4515     { 487, "Shenzhen Universal Intellisys Co Ltd" },
4516     { 488, "EK Intellisys Sdn Bhd" },
4517     { 489, "SysCom" },
4518     { 490, "Firecom, Inc." },
4519     { 491, "ESA Elektroschaltanlagen Grimma GmbH" },
4520     { 492, "Kumahira Co Ltd" },
4521     { 493, "Hotraco" },
4522     { 494, "SABO Elektronik GmbH" },
4523     { 495, "Equip'Trans" },
4524     { 496, "TCS Basys Controls" },
4525     { 497, "FlowCon International A/S" },
4526     { 498, "ThyssenKrupp Elevator Americas" },
4527     { 499, "Abatement Technologies" },
4528     { 500, "Continental Control Systems, LLC" },
4529     { 501, "WISAG Automatisierungstechnik GmbH & Co KG" },
4530     { 502, "EasyIO" },
4531     { 503, "EAP-Electric GmbH" },
4532     { 504, "Hardmeier" },
4533     { 505, "Mircom Group of Companies" },
4534     { 506, "Quest Controls" },
4535     { 507, "Mestek, Inc" },
4536     { 508, "Pulse Energy" },
4537     { 509, "Tachikawa Corporation" },
4538     { 510, "University of Nebraska-Lincoln" },
4539     { 511, "Redwood Systems" },
4540     { 512, "PASStec Industrie-Elektronik GmbH" },
4541     { 513, "NgEK, Inc." },
4542     { 514, "FAW Electronics Ltd" },
4543     { 515, "Jireh Energy Tech Co., Ltd." },
4544     { 516, "Enlighted Inc." },
4545     { 517, "El-Piast Sp. Z o.o" },
4546     { 518, "NetxAutomation Software GmbH" },
4547     { 519, "Invertek Drives" },
4548     { 520, "Deutschmann Automation GmbH & Co. KG" },
4549     { 521, "EMU Electronic AG" },
4550     { 522, "Phaedrus Limited" },
4551     { 523, "Sigmatek GmbH & Co KG" },
4552     { 524, "Marlin Controls" },
4553     { 525, "Circutor, SA" },
4554     { 526, "UTC Fire & Security" },
4555     { 527, "DENT Instruments, Inc." },
4556     { 528, "FHP Manufacturing Company - Bosch Group" },
4557     { 529, "GE Intelligent Platforms" },
4558     { 530, "Inner Range Pty Ltd" },
4559     { 531, "GLAS Energy Technology" },
4560     { 532, "MSR-Electronic-GmbH" },
4561     { 533, "Energy Control Systems, Inc." },
4562     { 534, "EMT Controls" },
4563     { 535, "Daintree Networks Inc." },
4564     { 536, "EURO ICC d.o.o" },
4565     { 537, "TE Connectivity Energy" },
4566     { 538, "GEZE GmbH" },
4567     { 539, "NEC Corporation" },
4568     { 540, "Ho Cheung International Company Limited" },
4569     { 541, "Sharp Manufacturing Systems Corporation" },
4570     { 542, "DOT CONTROLS a.s." },
4571     { 543, "BeaconMedaes" },
4572     { 544, "Midea Commercial Aircon" },
4573     { 545, "WattMaster Controls" },
4574     { 546, "Kamstrup A/S" },
4575     { 547, "CA Computer Automation GmbH" },
4576     { 548, "Laars Heating Systems Company" },
4577     { 549, "Hitachi Systems, Ltd." },
4578     { 550, "Fushan AKE Electronic Engineering Co., Ltd." },
4579     { 551, "Toshiba International Corporation" },
4580     { 552, "Starman Systems, LLC" },
4581     { 553, "Samsung Techwin Co., Ltd." },
4582     { 554, "ISAS-Integrated Switchgear and Systems P/L" },
4583     { 556, "Obvius" },
4584     { 557, "Marek Guzik" },
4585     { 558, "Vortek Instruments, LLC" },
4586     { 559, "Universal Lighting Technologies" },
4587     { 560, "Myers Power Products, Inc." },
4588     { 561, "Vector Controls GmbH" },
4589     { 562, "Crestron Electronics, Inc." },
4590     { 563, "A&E Controls Limited" },
4591     { 564, "Projektomontaza A.D." },
4592     { 565, "Freeaire Refrigeration" },
4593     { 566, "Aqua Cooler Pty Limited" },
4594     { 567, "Basic Controls" },
4595     { 568, "GE Measurement and Control Solutions Advanced Sensors" },
4596     { 569, "EQUAL Networks" },
4597     { 570, "Millennial Net" },
4598     { 571, "APLI Ltd" },
4599     { 572, "Electro Industries/GaugeTech" },
4600     { 573, "SangMyung University" },
4601     { 574, "Coppertree Analytics, Inc." },
4602     { 575, "CoreNetiX GmbH" },
4603     { 576, "Acutherm" },
4604     { 577, "Dr. Riedel Automatisierungstechnik GmbH" },
4605     { 578, "Shina System Co., Ltd" },
4606     { 579, "Iqapertus" },
4607     { 580, "PSE Technology" },
4608     { 581, "BA Systems" },
4609     { 582, "BTICINO" },
4610     { 583, "Monico, Inc." },
4611     { 584, "iCue" },
4612     { 585, "tekmar Control Systems Ltd." },
4613     { 586, "Control Technology Corporation" },
4614     { 587, "GFAE GmbH" },
4615     { 588, "BeKa Software GmbH" },
4616     { 589, "Isoil Industria SpA" },
4617     { 590, "Home Systems Consulting SpA" },
4618     { 591, "Socomec" },
4619     { 592, "Everex Communications, Inc." },
4620     { 593, "Ceiec Electric Technology" },
4621     { 594, "Atrila GmbH" },
4622     { 595, "WingTechs" },
4623     { 596, "Shenzhen Mek Intellisys Pte Ltd." },
4624     { 597, "Nestfield Co., Ltd." },
4625     { 598, "Swissphone Telecom AG" },
4626     { 599, "PNTECH JSC" },
4627     { 600, "Horner APG, LLC" },
4628     { 601, "PVI Industries, LLC" },
4629     { 602, "Ela-compil" },
4630     { 603, "Pegasus Automation International LLC" },
4631     { 604, "Wight Electronic Services Ltd." },
4632     { 605, "Marcom" },
4633     { 606, "Exhausto A/S" },
4634     { 607, "Dwyer Instruments, Inc." },
4635     { 608, "Link GmbH" },
4636     { 609, "Oppermann Regelgerate GmbH" },
4637     { 610, "NuAire, Inc." },
4638     { 611, "Nortec Humidity, Inc." },
4639     { 612, "Bigwood Systems, Inc." },
4640     { 613, "Enbala Power Networks" },
4641     { 614, "Inter Energy Co., Ltd." },
4642     { 615, "ETC" },
4643     { 616, "COMELEC S.A.R.L" },
4644     { 617, "Pythia Technologies" },
4645     { 618, "TrendPoint Systems, Inc." },
4646     { 619, "AWEX" },
4647     { 620, "Eurevia" },
4648     { 621, "Kongsberg E-lon AS" },
4649     { 622, "FlaktWoods" },
4650     { 623, "E + E Elektronik GES M.B.H." },
4651     { 624, "ARC Informatique" },
4652     { 625, "SKIDATA AG" },
4653     { 626, "WSW Solutions" },
4654     { 627, "Trefon Electronic GmbH" },
4655     { 628, "Dongseo System" },
4656     { 629, "Kanontec Intelligence Technology Co., Ltd." },
4657     { 630, "EVCO S.p.A." },
4658     { 631, "Accuenergy (CANADA) Inc." },
4659     { 632, "SoftDEL" },
4660     { 633, "Orion Energy Systems, Inc." },
4661     { 634, "Roboticsware" },
4662     { 635, "DOMIQ Sp. z o.o." },
4663     { 636, "Solidyne" },
4664     { 637, "Elecsys Corporation" },
4665     { 638, "Conditionaire International Pty. Limited" },
4666     { 639, "Quebec, Inc." },
4667     { 640, "Homerun Holdings" },
4668     { 641, "Murata Americas" },
4669     { 642, "Comptek" },
4670     { 643, "Westco Systems, Inc." },
4671     { 644, "Advancis Software & Services GmbH" },
4672     { 645, "Intergrid, LLC" },
4673     { 646, "Markerr Controls, Inc." },
4674     { 647, "Toshiba Elevator and Building Systems Corporation" },
4675     { 648, "Spectrum Controls, Inc." },
4676     { 649, "Mkservice" },
4677     { 650, "Fox Thermal Instruments" },
4678     { 651, "SyxthSense Ltd" },
4679     { 652, "DUHA System S R.O." },
4680     { 653, "NIBE" },
4681     { 654, "Melink Corporation" },
4682     { 655, "Fritz-Haber-Institut" },
4683     { 656, "MTU Onsite Energy GmbH, Gas Power Systems" },
4684     { 657, "Omega Engineering, Inc." },
4685     { 658, "Avelon" },
4686     { 659, "Ywire Technologies, Inc." },
4687     { 660, "M.R. Engineering Co., Ltd." },
4688     { 661, "Lochinvar, LLC" },
4689     { 662, "Sontay Limited" },
4690     { 663, "GRUPA Slawomir Chelminski" },
4691     { 664, "Arch Meter Corporation" },
4692     { 665, "Senva, Inc." },
4693     { 667, "FM-Tec" },
4694     { 668, "Systems Specialists, Inc." },
4695     { 669, "SenseAir" },
4696     { 670, "AB IndustrieTechnik Srl" },
4697     { 671, "Cortland Research, LLC" },
4698     { 672, "MediaView" },
4699     { 673, "VDA Elettronica" },
4700     { 674, "CSS, Inc." },
4701     { 675, "Tek-Air Systems, Inc." },
4702     { 676, "ICDT" },
4703     { 677, "The Armstrong Monitoring Corporation" },
4704     { 678, "DIXELL S.r.l" },
4705     { 679, "Lead System, Inc." },
4706     { 680, "ISM EuroCenter S.A." },
4707     { 681, "TDIS" },
4708     { 682, "Trade FIDES" },
4709     { 683, "Knuerr GmbH (Emerson Network Power)" },
4710     { 684, "Resource Data Management" },
4711     { 685, "Abies Technology, Inc." },
4712     { 686, "Amalva" },
4713     { 687, "MIRAE Electrical Mfg. Co., Ltd." },
4714     { 688, "HunterDouglas Architectural Projects Scandinavia ApS" },
4715     { 689, "RUNPAQ Group Co., Ltd" },
4716     { 690, "Unicard SA" },
4717     { 691, "IE Technologies" },
4718     { 692, "Ruskin Manufacturing" },
4719     { 693, "Calon Associates Limited" },
4720     { 694, "Contec Co., Ltd." },
4721     { 695, "iT GmbH" },
4722     { 696, "Autani Corporation" },
4723     { 697, "Christian Fortin" },
4724     { 698, "HDL" },
4725     { 699, "IPID Sp. Z.O.O Limited" },
4726     { 700, "Fuji Electric Co., Ltd" },
4727     { 701, "View, Inc." },
4728     { 702, "Samsung S1 Corporation" },
4729     { 703, "New Lift" },
4730     { 704, "VRT Systems" },
4731     { 705, "Motion Control Engineering, Inc." },
4732     { 706, "Weiss Klimatechnik GmbH" },
4733     { 707, "Elkon" },
4734     { 708, "Eliwell Controls S.r.l." },
4735     { 709, "Japan Computer Technos Corp" },
4736     { 710, "Rational Network ehf" },
4737     { 711, "Magnum Energy Solutions, LLC" },
4738     { 712, "MelRok" },
4739     { 713, "VAE Group" },
4740     { 714, "LGCNS" },
4741     { 715, "Berghof Automationstechnik GmbH" },
4742     { 716, "Quark Communications, Inc." },
4743     { 717, "Sontex" },
4744     { 718, "mivune AG" },
4745     { 719, "Panduit" },
4746     { 720, "Smart Controls, LLC" },
4747     { 721, "Compu-Aire, Inc." },
4748     { 722, "Sierra" },
4749     { 723, "ProtoSense Technologies" },
4750     { 724, "Eltrac Technologies Pvt Ltd" },
4751     { 725, "Bektas Invisible Controls GmbH" },
4752     { 726, "Entelec" },
4753     { 727, "Innexiv" },
4754     { 728, "Covenant" },
4755     { 729, "Davitor AB" },
4756     { 730, "TongFang Technovator" },
4757     { 731, "Building Robotics, Inc." },
4758     { 732, "HSS-MSR UG" },
4759     { 733, "FramTack LLC" },
4760     { 734, "B. L. Acoustics, Ltd." },
4761     { 735, "Traxxon Rock Drills, Ltd" },
4762     { 736, "Franke" },
4763     { 737, "Wurm GmbH & Co" },
4764     { 738, "AddENERGIE" },
4765     { 739, "Mirle Automation Corporation" },
4766     { 740, "Ibis Networks" },
4767     { 741, "ID-KARTA s.r.o." },
4768     { 742, "Anaren, Inc." },
4769     { 743, "Span, Incorporated" },
4770     { 744, "Bosch Thermotechnology Corp" },
4771     { 745, "DRC Technology S.A." },
4772     { 746, "Shanghai Energy Building Technology Co, Ltd" },
4773     { 747, "Fraport AG" },
4774     { 748, "Flowgroup" },
4775     { 749, "Skytron Energy, GmbH" },
4776     { 750, "ALTEL Wicha, Golda Sp. J." },
4777     { 751, "Drupal" },
4778     { 752, "Axiomatic Technology, Ltd" },
4779     { 753, "Bohnke + Partner" },
4780     { 754, "Function 1" },
4781     { 755, "Optergy Pty, Ltd" },
4782     { 756, "LSI Virticus" },
4783     { 757, "Konzeptpark GmbH" },
4784     { 758, "Hubbell Building Automation, Inc." },
4785     { 759, "eCurv, Inc." },
4786     { 760, "Agnosys GmbH" },
4787     { 761, "Shanghai Sunfull Automation Co., LTD" },
4788     { 762, "Kurz Instruments, Inc." },
4789     { 763, "Cias Elettronica S.r.l." },
4790     { 764, "Multiaqua, Inc." },
4791     { 765, "BlueBox" },
4792     { 766, "Sensidyne" },
4793     { 767, "Viessmann Elektronik GmbH" },
4794     { 768, "ADFweb.com srl" },
4795     { 769, "Gaylord Industries" },
4796     { 770, "Majur Ltd." },
4797     { 771, "Shanghai Huilin Technology Co., Ltd." },
4798     { 772, "Exotronic" },
4799     { 773, "Safecontrol spol s.r.o." },
4800     { 774, "Amatis" },
4801     { 775, "Universal Electric Corporation" },
4802     { 776, "iBACnet" },
4803     { 778, "Smartrise Engineering, Inc." },
4804     { 779, "Miratron, Inc." },
4805     { 780, "SmartEdge" },
4806     { 781, "Mitsubishi Electric Australia Pty Ltd" },
4807     { 782, "Triangle Research International Ptd Ltd" },
4808     { 783, "Produal Oy" },
4809     { 784, "Milestone Systems A/S" },
4810     { 785, "Trustbridge" },
4811     { 0, NULL }
4812 };
4813 static value_string_ext BACnetVendorIdentifiers_ext = VALUE_STRING_EXT_INIT(BACnetVendorIdentifiers);
4814
4815 static int proto_bacapp = -1;
4816 static int hf_bacapp_type = -1;
4817 static int hf_bacapp_pduflags = -1;
4818 static int hf_bacapp_SEG = -1;
4819 static int hf_bacapp_MOR = -1;
4820 static int hf_bacapp_SA = -1;
4821 static int hf_bacapp_response_segments = -1;
4822 static int hf_bacapp_max_adpu_size = -1;
4823 static int hf_bacapp_invoke_id = -1;
4824 static int hf_bacapp_objectType = -1;
4825 static int hf_bacapp_instanceNumber = -1;
4826 static int hf_bacapp_sequence_number = -1;
4827 static int hf_bacapp_window_size = -1;
4828 static int hf_bacapp_service = -1;
4829 static int hf_bacapp_NAK = -1;
4830 static int hf_bacapp_SRV = -1;
4831 static int hf_Device_Instance_Range_Low_Limit = -1;
4832 static int hf_Device_Instance_Range_High_Limit = -1;
4833 static int hf_BACnetRejectReason = -1;
4834 static int hf_BACnetAbortReason = -1;
4835 static int hf_BACnetApplicationTagNumber = -1;
4836 static int hf_BACnetContextTagNumber = -1;
4837 static int hf_BACnetExtendedTagNumber = -1;
4838 static int hf_BACnetNamedTag = -1;
4839 static int hf_BACnetTagClass = -1;
4840 static int hf_BACnetCharacterSet = -1;
4841 static int hf_bacapp_tag_lvt = -1;
4842 static int hf_bacapp_tag_ProcessId = -1;
4843 static int hf_bacapp_uservice = -1;
4844 static int hf_BACnetPropertyIdentifier = -1;
4845 static int hf_BACnetVendorIdentifier = -1;
4846 static int hf_BACnetRestartReason = -1;
4847 static int hf_bacapp_tag_IPV4 = -1;
4848 static int hf_bacapp_tag_IPV6 = -1;
4849 static int hf_bacapp_tag_PORT = -1;
4850 /* some more variables for segmented messages */
4851 static int hf_msg_fragments = -1;
4852 static int hf_msg_fragment = -1;
4853 static int hf_msg_fragment_overlap = -1;
4854 static int hf_msg_fragment_overlap_conflicts = -1;
4855 static int hf_msg_fragment_multiple_tails = -1;
4856 static int hf_msg_fragment_too_long_fragment = -1;
4857 static int hf_msg_fragment_error = -1;
4858 static int hf_msg_fragment_count = -1;
4859 static int hf_msg_reassembled_in = -1;
4860 static int hf_msg_reassembled_length = -1;
4861
4862 static gint ett_msg_fragment = -1;
4863 static gint ett_msg_fragments = -1;
4864
4865 static gint ett_bacapp = -1;
4866 static gint ett_bacapp_control = -1;
4867 static gint ett_bacapp_tag = -1;
4868 static gint ett_bacapp_list = -1;
4869 static gint ett_bacapp_value = -1;
4870
4871 static expert_field ei_bacapp_bad_length = EI_INIT;
4872
4873 static gint32 propertyIdentifier = -1;
4874 static gint32 propertyArrayIndex = -1;
4875 static guint32 object_type = 4096;
4876
4877 static guint8 bacapp_flags = 0;
4878 static guint8 bacapp_seq = 0;
4879
4880 /* Defined to allow vendor identifier registration of private transfer dissectors */
4881 static dissector_table_t bacapp_dissector_table;
4882
4883
4884 /* Stat: BACnet Packets sorted by IP */
4885 bacapp_info_value_t bacinfo;
4886
4887 static const gchar* st_str_packets_by_ip = "BACnet Packets by IP";
4888 static const gchar* st_str_packets_by_ip_dst = "By Destination";
4889 static const gchar* st_str_packets_by_ip_src = "By Source";
4890 static int st_node_packets_by_ip = -1;
4891 static int st_node_packets_by_ip_dst = -1;
4892 static int st_node_packets_by_ip_src = -1;
4893
4894 static void
4895 bacapp_packet_stats_tree_init(stats_tree* st)
4896 {
4897     st_node_packets_by_ip = stats_tree_create_pivot(st, st_str_packets_by_ip, 0);
4898     st_node_packets_by_ip_src = stats_tree_create_node(st, st_str_packets_by_ip_src, st_node_packets_by_ip, TRUE);
4899     st_node_packets_by_ip_dst = stats_tree_create_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, TRUE);
4900 }
4901
4902 static gchar *
4903 bacapp_get_address_label(const char *tag, address *addr)
4904 {
4905     gchar *addr_str, *label_str;
4906
4907     addr_str = address_to_str(NULL, addr);
4908     label_str = wmem_strconcat(NULL, tag, addr_str, NULL);
4909     wmem_free(NULL, addr_str);
4910     return label_str;
4911 }
4912
4913 static int
4914 bacapp_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4915 {
4916     int    packets_for_this_dst;
4917     int    packets_for_this_src;
4918     int    service_for_this_dst;
4919     int    service_for_this_src;
4920     int    src_for_this_dst;
4921     int    dst_for_this_src;
4922     int    objectid_for_this_dst;
4923     int    objectid_for_this_src;
4924     int    instanceid_for_this_dst;
4925     int    instanceid_for_this_src;
4926     gchar *dststr;
4927     gchar *srcstr;
4928     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4929
4930     srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
4931     dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
4932
4933     tick_stat_node(st, st_str_packets_by_ip, 0, TRUE);
4934     packets_for_this_dst = tick_stat_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, TRUE);
4935     packets_for_this_src = tick_stat_node(st, st_str_packets_by_ip_src, st_node_packets_by_ip, TRUE);
4936     src_for_this_dst     = tick_stat_node(st, dststr, packets_for_this_dst, TRUE);
4937     dst_for_this_src     = tick_stat_node(st, srcstr, packets_for_this_src, TRUE);
4938     service_for_this_src = tick_stat_node(st, dststr, dst_for_this_src, TRUE);
4939     service_for_this_dst = tick_stat_node(st, srcstr, src_for_this_dst, TRUE);
4940     if (binfo->service_type) {
4941         objectid_for_this_dst = tick_stat_node(st, binfo->service_type, service_for_this_dst, TRUE);
4942         objectid_for_this_src = tick_stat_node(st, binfo->service_type, service_for_this_src, TRUE);
4943         if (binfo->object_ident) {
4944             instanceid_for_this_dst = tick_stat_node(st, binfo->object_ident, objectid_for_this_dst, TRUE);
4945             tick_stat_node(st, binfo->instance_ident, instanceid_for_this_dst, FALSE);
4946             instanceid_for_this_src = tick_stat_node(st, binfo->object_ident, objectid_for_this_src, TRUE);
4947             tick_stat_node(st, binfo->instance_ident, instanceid_for_this_src, FALSE);
4948         }
4949     }
4950
4951     wmem_free(NULL, srcstr);
4952     wmem_free(NULL, dststr);
4953
4954     return 1;
4955 }
4956
4957 /* Stat: BACnet Packets sorted by Service */
4958 static const gchar* st_str_packets_by_service = "BACnet Packets by Service";
4959 static int st_node_packets_by_service = -1;
4960
4961 static void
4962 bacapp_service_stats_tree_init(stats_tree* st)
4963 {
4964     st_node_packets_by_service = stats_tree_create_pivot(st, st_str_packets_by_service, 0);
4965 }
4966
4967 static int
4968 bacapp_stats_tree_service(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4969 {
4970     int    servicetype;
4971     int    src, dst;
4972     int    objectid;
4973
4974     gchar *dststr;
4975     gchar *srcstr;
4976
4977     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4978
4979     srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
4980     dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
4981
4982     tick_stat_node(st, st_str_packets_by_service, 0, TRUE);
4983     if (binfo->service_type) {
4984         servicetype = tick_stat_node(st, binfo->service_type, st_node_packets_by_service, TRUE);
4985         src         = tick_stat_node(st, srcstr, servicetype, TRUE);
4986         dst         = tick_stat_node(st, dststr, src, TRUE);
4987         if (binfo->object_ident) {
4988             objectid = tick_stat_node(st, binfo->object_ident, dst, TRUE);
4989             tick_stat_node(st, binfo->instance_ident, objectid, FALSE);
4990         }
4991     }
4992
4993     wmem_free(NULL, srcstr);
4994     wmem_free(NULL, dststr);
4995
4996     return 1;
4997 }
4998
4999 /* Stat: BACnet Packets sorted by Object Type */
5000 static const gchar* st_str_packets_by_objectid = "BACnet Packets by Object Type";
5001 static int st_node_packets_by_objectid = -1;
5002
5003 static void
5004 bacapp_objectid_stats_tree_init(stats_tree* st)
5005 {
5006     st_node_packets_by_objectid = stats_tree_create_pivot(st, st_str_packets_by_objectid, 0);
5007 }
5008
5009 static int
5010 bacapp_stats_tree_objectid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
5011 {
5012     int    servicetype;
5013     int    src, dst;
5014     int    objectid;
5015
5016     gchar *dststr;
5017     gchar *srcstr;
5018     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
5019
5020     srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
5021     dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
5022
5023     tick_stat_node(st, st_str_packets_by_objectid, 0, TRUE);
5024     if (binfo->object_ident) {
5025         objectid = tick_stat_node(st, binfo->object_ident, st_node_packets_by_objectid, TRUE);
5026         src = tick_stat_node(st, srcstr, objectid, TRUE);
5027         dst = tick_stat_node(st, dststr, src, TRUE);
5028         if (binfo->service_type) {
5029             servicetype = tick_stat_node(st, binfo->service_type, dst, TRUE);
5030             tick_stat_node(st, binfo->instance_ident, servicetype, FALSE);
5031         }
5032     }
5033
5034     wmem_free(NULL, srcstr);
5035     wmem_free(NULL, dststr);
5036
5037     return 1;
5038 }
5039
5040 /* Stat: BACnet Packets sorted by Instance No */
5041 static const gchar* st_str_packets_by_instanceid  = "BACnet Packets by Instance ID";
5042 static int          st_node_packets_by_instanceid = -1;
5043
5044 static void
5045 bacapp_instanceid_stats_tree_init(stats_tree* st)
5046 {
5047     st_node_packets_by_instanceid = stats_tree_create_pivot(st, st_str_packets_by_instanceid, 0);
5048 }
5049
5050 static int
5051 bacapp_stats_tree_instanceid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
5052 {
5053     int    servicetype;
5054     int    src, dst;
5055     int    instanceid;
5056
5057     gchar *dststr;
5058     gchar *srcstr;
5059     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
5060
5061     srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
5062     dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
5063
5064     tick_stat_node(st, st_str_packets_by_instanceid, 0, TRUE);
5065     if (binfo->object_ident) {
5066         instanceid = tick_stat_node(st, binfo->instance_ident, st_node_packets_by_instanceid, TRUE);
5067         src = tick_stat_node(st, srcstr, instanceid, TRUE);
5068         dst = tick_stat_node(st, dststr, src, TRUE);
5069         if (binfo->service_type) {
5070             servicetype = tick_stat_node(st, binfo->service_type, dst, TRUE);
5071             tick_stat_node(st, binfo->object_ident, servicetype, FALSE);
5072         }
5073     }
5074
5075     wmem_free(NULL, srcstr);
5076     wmem_free(NULL, dststr);
5077
5078     return 1;
5079 }
5080
5081
5082 /* register all BACnet Ststistic trees */
5083 static void
5084 register_bacapp_stat_trees(void)
5085 {
5086     stats_tree_register("bacapp", "bacapp_ip", "BACnet/Packets sorted by IP", 0,
5087         bacapp_stats_tree_packet, bacapp_packet_stats_tree_init, NULL);
5088     stats_tree_register("bacapp", "bacapp_service", "BACnet/Packets sorted by Service", 0,
5089         bacapp_stats_tree_service, bacapp_service_stats_tree_init, NULL);
5090     stats_tree_register("bacapp", "bacapp_objectid", "BACnet/Packets sorted by Object Type", 0,
5091         bacapp_stats_tree_objectid, bacapp_objectid_stats_tree_init, NULL);
5092     stats_tree_register("bacapp", "bacapp_instanceid", "BACnet/Packets sorted by Instance ID", 0,
5093         bacapp_stats_tree_instanceid, bacapp_instanceid_stats_tree_init, NULL);
5094 }
5095
5096 /* 'data' must be allocated with wmem packet scope */
5097 static gint
5098 updateBacnetInfoValue(gint whichval, const gchar *data)
5099 {
5100     if (whichval == BACINFO_SERVICE) {
5101         bacinfo.service_type = data;
5102         return 0;
5103     }
5104     if (whichval == BACINFO_INVOKEID) {
5105         bacinfo.invoke_id = data;
5106         return 0;
5107     }
5108     if (whichval == BACINFO_OBJECTID) {
5109         bacinfo.object_ident = data;
5110         return 0;
5111     }
5112     if (whichval == BACINFO_INSTANCEID) {
5113         bacinfo.instance_ident = data;
5114         return 0;
5115     }
5116     return -1;
5117 }
5118
5119 static const fragment_items msg_frag_items = {
5120     /* Fragment subtrees */
5121     &ett_msg_fragment,
5122     &ett_msg_fragments,
5123     /* Fragment fields */
5124     &hf_msg_fragments,
5125     &hf_msg_fragment,
5126     &hf_msg_fragment_overlap,
5127     &hf_msg_fragment_overlap_conflicts,
5128     &hf_msg_fragment_multiple_tails,
5129     &hf_msg_fragment_too_long_fragment,
5130     &hf_msg_fragment_error,
5131     &hf_msg_fragment_count,
5132     /* Reassembled in field */
5133     &hf_msg_reassembled_in,
5134     /* Reassembled length field */
5135     &hf_msg_reassembled_length,
5136     /* Reassembled data field */
5137     NULL,
5138     /* Tag */
5139     "Message fragments"
5140 };
5141
5142 #if 0
5143 /* if BACnet uses the reserved values, then patch the corresponding values here, maximum 16 values are defined */
5144 /* FIXME: fGetMaxAPDUSize is commented out, as it is not used. It was used to set variables which were not later used. */
5145 static const guint MaxAPDUSize [] = { 50, 128, 206, 480, 1024, 1476 };
5146
5147 static guint
5148 fGetMaxAPDUSize(guint8 idx)
5149 {
5150     /* only 16 values are defined, so use & 0x0f */
5151     /* check the size of the Array, deliver either the entry
5152        or the first entry if idx is outside of the array (bug 3736 comment#7) */
5153
5154     if ((idx & 0x0f) >= (gint)(sizeof(MaxAPDUSize)/sizeof(guint)))
5155         return MaxAPDUSize[0];
5156     else
5157         return MaxAPDUSize[idx & 0x0f];
5158 }
5159 #endif
5160
5161 static const char*
5162 val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
5163     const char *fmt, const char *split_fmt)
5164     G_GNUC_PRINTF(4, 0)
5165     G_GNUC_PRINTF(5, 0);
5166
5167 /* Used when there are ranges of reserved and proprietary enumerations */
5168 static const char*
5169 val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
5170     const char *fmt, const char *split_fmt)
5171 {
5172     if (val < split_val)
5173         return val_to_str(val, vs, fmt);
5174     else
5175         return val_to_str(val, vs, split_fmt);
5176 }
5177
5178 /* from clause 20.2.1.3.2 Constructed Data */
5179 /* returns true if the extended value is used */
5180 static gboolean
5181 tag_is_extended_value(guint8 tag)
5182 {
5183     return (tag & 0x07) == 5;
5184 }
5185
5186 static gboolean
5187 tag_is_opening(guint8 tag)
5188 {
5189     return (tag & 0x07) == 6;
5190 }
5191
5192 static gboolean
5193 tag_is_closing(guint8 tag)
5194 {
5195     return (tag & 0x07) == 7;
5196 }
5197
5198 /* from clause 20.2.1.1 Class
5199    class bit shall be one for context specific tags */
5200 /* returns true if the tag is context specific */
5201 static gboolean
5202 tag_is_context_specific(guint8 tag)
5203 {
5204     return (tag & 0x08) != 0;
5205 }
5206
5207 static gboolean
5208 tag_is_extended_tag_number(guint8 tag)
5209 {
5210     return ((tag & 0xF0) == 0xF0);
5211 }
5212
5213 static guint32
5214 object_id_type(guint32 object_identifier)
5215 {
5216     return ((object_identifier >> 22) & 0x3FF);
5217 }
5218
5219 static guint32
5220 object_id_instance(guint32 object_identifier)
5221 {
5222     return (object_identifier & 0x3FFFFF);
5223 }
5224
5225 static guint
5226 fTagNo(tvbuff_t *tvb, guint offset)
5227 {
5228     return (guint)(tvb_get_guint8(tvb, offset) >> 4);
5229 }
5230
5231 static gboolean
5232 fUnsigned32(tvbuff_t *tvb, guint offset, guint32 lvt, guint32 *val)
5233 {
5234     gboolean valid = TRUE;
5235
5236     switch (lvt) {
5237     case 1:
5238         *val = tvb_get_guint8(tvb, offset);
5239         break;
5240     case 2:
5241         *val = tvb_get_ntohs(tvb, offset);
5242         break;
5243     case 3:
5244         *val = tvb_get_ntoh24(tvb, offset);
5245         break;
5246     case 4:
5247         *val = tvb_get_ntohl(tvb, offset);
5248         break;
5249     default:
5250         valid = FALSE;
5251         break;
5252     }
5253
5254     return valid;
5255 }
5256
5257 static gboolean
5258 fUnsigned64(tvbuff_t *tvb, guint offset, guint32 lvt, guint64 *val)
5259 {
5260     gboolean valid = FALSE;
5261     gint64   value = 0;
5262     guint8   data, i;
5263
5264     if (lvt && (lvt <= 8)) {
5265         valid = TRUE;
5266         for (i = 0; i < lvt; i++) {
5267             data = tvb_get_guint8(tvb, offset+i);
5268             value = (value << 8) + data;
5269         }
5270         *val = value;
5271     }
5272
5273     return valid;
5274 }
5275
5276 /* BACnet Signed Value uses 2's complement notation, but with a twist:
5277    All signed integers shall be encoded in the smallest number of octets
5278    possible.  That is, the first octet of any multi-octet encoded value
5279    shall not be X'00' if the most significant bit (bit 7) of the second
5280    octet is 0, and the first octet shall not be X'FF' if the most
5281    significant bit of the second octet is 1. ASHRAE-135-2004-20.2.5 */
5282 static gboolean
5283 fSigned64(tvbuff_t *tvb, guint offset, guint32 lvt, gint64 *val)
5284 {
5285     gboolean valid = FALSE;
5286     gint64   value = 0;
5287     guint8   data;
5288     guint32  i;
5289
5290     /* we can only handle 7 bytes for a 64-bit value due to signed-ness */
5291     if (lvt && (lvt <= 7)) {
5292         valid = TRUE;
5293         data = tvb_get_guint8(tvb, offset);
5294         if ((data & 0x80) != 0)
5295             value = (-1 << 8) | data;
5296         else
5297             value = data;
5298         for (i = 1; i < lvt; i++) {
5299             data = tvb_get_guint8(tvb, offset+i);
5300             value = (value << 8) + data;
5301         }
5302         *val = value;
5303     }
5304
5305     return valid;
5306 }
5307
5308 static guint
5309 fTagHeaderTree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5310     guint offset, guint8 *tag_no, guint8* tag_info, guint32 *lvt)
5311 {
5312     proto_item *ti = NULL;
5313     guint8      tag;
5314     guint8      value;
5315     guint       tag_len = 1;
5316     guint       lvt_len = 1;    /* used for tree display of lvt */
5317     guint       lvt_offset;     /* used for tree display of lvt */
5318
5319     lvt_offset = offset;
5320     tag        = tvb_get_guint8(tvb, offset);
5321     *tag_info  = 0;
5322     *lvt       = tag & 0x07;
5323
5324     /* To solve the problem of lvt values of 6/7 being indeterminate - it */
5325     /* can mean open/close tag or length of 6/7 after the length is */
5326     /* computed below - store whole tag info, not just context bit. */
5327     if (tag_is_context_specific(tag)) *tag_info = tag & 0x0F;
5328     *tag_no = tag >> 4;
5329     if (tag_is_extended_tag_number(tag)) {
5330         *tag_no = tvb_get_guint8(tvb, offset + tag_len++);
5331     }
5332     if (tag_is_extended_value(tag)) {       /* length is more than 4 Bytes */
5333         lvt_offset += tag_len;
5334         value = tvb_get_guint8(tvb, lvt_offset);
5335         tag_len++;
5336         if (value == 254) { /* length is encoded with 16 Bits */
5337             *lvt = tvb_get_ntohs(tvb, lvt_offset+1);
5338             tag_len += 2;
5339             lvt_len += 2;
5340         } else if (value == 255) { /* length is encoded with 32 Bits */
5341             *lvt = tvb_get_ntohl(tvb, lvt_offset+1);
5342             tag_len += 4;
5343             lvt_len += 4;
5344         } else
5345             *lvt = value;
5346     }
5347
5348     if (tree) {
5349         proto_tree *subtree;
5350         if (tag_is_opening(tag))
5351             ti = proto_tree_add_text(tree, tvb, offset, tag_len, "{[%u]", *tag_no );
5352         else if (tag_is_closing(tag))
5353             ti = proto_tree_add_text(tree, tvb, offset, tag_len, "}[%u]", *tag_no );
5354         else if (tag_is_context_specific(tag)) {
5355             ti = proto_tree_add_text(tree, tvb, offset, tag_len,
5356                                      "Context Tag: %u, Length/Value/Type: %u",
5357                                      *tag_no, *lvt);
5358         } else
5359             ti = proto_tree_add_text(tree, tvb, offset, tag_len,
5360                                      "Application Tag: %s, Length/Value/Type: %u",
5361                                      val_to_str(*tag_no,
5362                                                 BACnetApplicationTagNumber,
5363                                                 ASHRAE_Reserved_Fmt),
5364                                      *lvt);
5365
5366         /* details if needed */
5367         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5368         proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, ENC_BIG_ENDIAN);
5369         if (tag_is_extended_tag_number(tag)) {
5370             proto_tree_add_uint_format(subtree,
5371                                        hf_BACnetContextTagNumber,
5372                                        tvb, offset, 1, tag,
5373                                        "Extended Tag Number");
5374             proto_tree_add_item(subtree,
5375                                 hf_BACnetExtendedTagNumber,
5376                                 tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5377         } else {
5378             if (tag_is_context_specific(tag))
5379                 proto_tree_add_item(subtree,
5380                                     hf_BACnetContextTagNumber,
5381                                     tvb, offset, 1, ENC_BIG_ENDIAN);
5382             else
5383                 proto_tree_add_item(subtree,
5384                                     hf_BACnetApplicationTagNumber,
5385                                     tvb, offset, 1, ENC_BIG_ENDIAN);
5386         }
5387         if (tag_is_closing(tag) || tag_is_opening(tag))
5388             proto_tree_add_item(subtree,
5389                                 hf_BACnetNamedTag,
5390                                 tvb, offset, 1, ENC_BIG_ENDIAN);
5391         else if (tag_is_extended_value(tag)) {
5392             proto_tree_add_item(subtree,
5393                                 hf_BACnetNamedTag,
5394                                 tvb, offset, 1, ENC_BIG_ENDIAN);
5395             proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
5396                                 tvb, lvt_offset, lvt_len, *lvt);
5397         } else
5398             proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
5399                                 tvb, lvt_offset, lvt_len, *lvt);
5400     } /* if (tree) */
5401
5402     if (*lvt > tvb_reported_length(tvb)) {
5403         expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
5404                                "LVT length too long: %d > %d", *lvt,
5405                                tvb_reported_length(tvb));
5406         *lvt = 1;
5407     }
5408
5409     return tag_len;
5410 }
5411
5412 static guint
5413 fTagHeader(tvbuff_t *tvb, packet_info *pinfo, guint offset, guint8 *tag_no, guint8* tag_info,
5414     guint32 *lvt)
5415 {
5416     return fTagHeaderTree(tvb, pinfo, NULL, offset, tag_no, tag_info, lvt);
5417 }
5418
5419 static guint
5420 fNullTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5421 {
5422     guint8      tag_no, tag_info;
5423     guint32     lvt;
5424     proto_tree *subtree;
5425
5426     subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "%sNULL", label);
5427     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5428
5429     return offset + 1;
5430 }
5431
5432 static guint
5433 fBooleanTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5434 {
5435     guint8      tag_no, tag_info;
5436     guint32     lvt      = 0;
5437     proto_tree *subtree;
5438     guint       bool_len = 1;
5439
5440     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5441     if (tag_info && lvt == 1) {
5442         lvt = tvb_get_guint8(tvb, offset+1);
5443         ++bool_len;
5444     }
5445
5446     subtree = proto_tree_add_subtree_format(tree, tvb, offset, bool_len,
5447                              ett_bacapp_tag, NULL, "%s%s", label, lvt == 0 ? "FALSE" : "TRUE");
5448     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5449
5450     return offset + bool_len;
5451 }
5452
5453 static guint
5454 fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5455 {
5456     guint64     val = 0;
5457     guint8      tag_no, tag_info;
5458     guint32     lvt;
5459     guint       tag_len;
5460     proto_tree *subtree;
5461
5462     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5463     /* only support up to an 8 byte (64-bit) integer */
5464     if (fUnsigned64(tvb, offset + tag_len, lvt, &val))
5465         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5466             ett_bacapp_tag, NULL, "%s(Unsigned) %" G_GINT64_MODIFIER "u", label, val);
5467     else
5468         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5469             ett_bacapp_tag, NULL, "%s - %u octets (Unsigned)", label, lvt);
5470     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5471
5472     return offset+tag_len+lvt;
5473 }
5474
5475 static guint
5476 fDevice_Instance(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, int hf)
5477 {
5478     guint8      tag_no, tag_info;
5479     guint32     lvt, safe_lvt;
5480     guint       tag_len;
5481     proto_item *ti;
5482     proto_tree *subtree;
5483
5484     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5485
5486     if (lvt > 4)
5487         safe_lvt = 4;
5488     else
5489         safe_lvt = lvt;
5490
5491     ti = proto_tree_add_item(tree, hf, tvb, offset+tag_len, safe_lvt, ENC_BIG_ENDIAN);
5492
5493     if (lvt != safe_lvt)
5494         expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
5495                 "This field claims to be an impossible %u bytes, while the max is %u", lvt, safe_lvt);
5496
5497     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5498     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5499
5500     return offset+tag_len+lvt;
5501 }
5502
5503 /* set split_val to zero when not needed */
5504 static guint
5505 fEnumeratedTagSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5506     guint offset, const gchar *label, const value_string *vs, guint32 split_val)
5507 {
5508     guint32     val = 0;
5509     guint8      tag_no, tag_info;
5510     guint32     lvt;
5511     guint       tag_len;
5512     proto_tree *subtree;
5513
5514     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5515     /* only support up to a 4 byte (32-bit) enumeration */
5516     if (fUnsigned32(tvb, offset+tag_len, lvt, &val)) {
5517         if (vs)
5518             subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5519                 ett_bacapp_tag, NULL, "%s %s", label, val_to_split_str(val, split_val, vs,
5520                 ASHRAE_Reserved_Fmt, Vendor_Proprietary_Fmt));
5521         else
5522             subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5523                 ett_bacapp_tag, NULL, "%s %u", label, val);
5524     } else {
5525         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5526             ett_bacapp_tag, NULL, "%s - %u octets (enumeration)", label, lvt);
5527     }
5528
5529     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5530
5531     return offset+tag_len+lvt;
5532 }
5533
5534 static guint
5535 fEnumeratedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5536         guint offset, const gchar *label, const value_string *vs)
5537 {
5538     return fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, vs, 0);
5539 }
5540
5541 static guint
5542 fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5543 {
5544     gint64      val = 0;
5545     guint8      tag_no, tag_info;
5546     guint32     lvt;
5547     guint       tag_len;
5548     proto_tree *subtree;
5549
5550     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5551     if (fSigned64(tvb, offset + tag_len, lvt, &val))
5552         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5553             ett_bacapp_tag, NULL, "%s(Signed) %" G_GINT64_MODIFIER "d", label, val);
5554     else
5555         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5556             ett_bacapp_tag, NULL, "%s - %u octets (Signed)", label, lvt);
5557     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5558
5559     return offset+tag_len+lvt;
5560 }
5561
5562 static guint
5563 fRealTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5564 {
5565     guint8      tag_no, tag_info;
5566     guint32     lvt;
5567     guint       tag_len;
5568     gfloat      f_val;
5569     proto_tree *subtree;
5570
5571     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5572     f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
5573     subtree = proto_tree_add_subtree_format(tree, tvb, offset, 4+tag_len,
5574         ett_bacapp_tag, NULL, "%s%f (Real)", label, f_val);
5575     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5576
5577     return offset+tag_len+4;
5578 }
5579
5580 static guint
5581 fDoubleTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5582 {
5583     guint8 tag_no, tag_info;
5584     guint32 lvt;
5585     guint tag_len;
5586     gdouble d_val;
5587     proto_tree *subtree;
5588
5589     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5590     d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
5591     subtree = proto_tree_add_subtree_format(tree, tvb, offset, 8+tag_len,
5592         ett_bacapp_tag, NULL, "%s%f (Double)", label, d_val);
5593     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5594
5595     return offset+tag_len+8;
5596 }
5597
5598 static guint
5599 fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5600 {
5601     guint32     val = 0, lvt;
5602     guint8      tag_no, tag_info;
5603     proto_item *ti;
5604     proto_tree *subtree;
5605     guint       tag_len;
5606
5607     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5608     if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
5609     {
5610         ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
5611             tvb, offset, lvt+tag_len, val);
5612         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5613     }
5614     else
5615     {
5616         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5617             ett_bacapp_tag, NULL, "Process Identifier - %u octets (Signed)", lvt);
5618     }
5619     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5620     offset += tag_len + lvt;
5621
5622     return offset;
5623 }
5624
5625 static guint
5626 fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5627 {
5628     guint32     val = 0, lvt;
5629     guint8      tag_no, tag_info;
5630     proto_tree *subtree;
5631     guint       tag_len;
5632
5633     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5634     if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
5635         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5636             ett_bacapp_tag, NULL,
5637             "%s (hh.mm.ss): %d.%02d.%02d%s",
5638             label,
5639             (val / 3600), ((val % 3600) / 60), (val % 60),
5640             val == 0 ? " (indefinite)" : "");
5641     else
5642         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5643             ett_bacapp_tag, NULL,
5644             "%s - %u octets (Signed)", label, lvt);
5645     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5646
5647     return offset+tag_len+lvt;
5648 }
5649
5650 static guint
5651 fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5652 {
5653     guint32     month, weekOfMonth, dayOfWeek;
5654     guint8      tag_no, tag_info;
5655     guint32     lvt;
5656     guint       tag_len;
5657     proto_tree *subtree;
5658
5659     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5660     month = tvb_get_guint8(tvb, offset+tag_len);
5661     weekOfMonth = tvb_get_guint8(tvb, offset+tag_len+1);
5662     dayOfWeek = tvb_get_guint8(tvb, offset+tag_len+2);
5663     subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5664                  ett_bacapp_tag, NULL, "%s %s, %s",
5665                  val_to_str(month, months, "month (%d) not found"),
5666                  val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"),
5667                  val_to_str(dayOfWeek, day_of_week, "day of week (%d) not found"));
5668     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5669
5670     return offset+tag_len+lvt;
5671 }
5672
5673 static guint
5674 fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5675 {
5676     guint32     year, month, day, weekday;
5677     guint8      tag_no, tag_info;
5678     guint32     lvt;
5679     guint       tag_len;
5680     proto_tree *subtree;
5681
5682     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5683     year    = tvb_get_guint8(tvb, offset+tag_len);
5684     month   = tvb_get_guint8(tvb, offset+tag_len+1);
5685     day     = tvb_get_guint8(tvb, offset+tag_len+2);
5686     weekday = tvb_get_guint8(tvb, offset+tag_len+3);
5687     if ((year == 255) && (day == 255) && (month == 255) && (weekday == 255)) {
5688         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5689             ett_bacapp_tag, NULL,
5690             "%sany", label);
5691     }
5692     else if (year != 255) {
5693         year += 1900;
5694         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5695             ett_bacapp_tag, NULL,
5696             "%s%s %d, %d, (Day of Week = %s)",
5697             label, val_to_str(month,
5698                 months,
5699                 "month (%d) not found"),
5700             day, year, val_to_str(weekday,
5701                 day_of_week,
5702                 "(%d) not found"));
5703     } else {
5704         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5705             ett_bacapp_tag, NULL,
5706             "%s%s %d, any year, (Day of Week = %s)",
5707             label, val_to_str(month, months, "month (%d) not found"),
5708             day, val_to_str(weekday, day_of_week, "(%d) not found"));
5709     }
5710     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5711
5712     return offset+tag_len+lvt;
5713 }
5714
5715 static guint
5716 fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5717 {
5718     guint32     hour, minute, second, msec, lvt;
5719     guint8      tag_no, tag_info;
5720     guint       tag_len;
5721     proto_tree *subtree;
5722
5723     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5724     hour    = tvb_get_guint8(tvb, offset+tag_len);
5725     minute  = tvb_get_guint8(tvb, offset+tag_len+1);
5726     second  = tvb_get_guint8(tvb, offset+tag_len+2);
5727     msec    = tvb_get_guint8(tvb, offset+tag_len+3);
5728     if ((hour == 255) && (minute == 255) && (second == 255) && (msec == 255))
5729         subtree = proto_tree_add_subtree_format(tree, tvb, offset,
5730             lvt+tag_len, ett_bacapp_tag, NULL,
5731             "%sany", label);
5732     else
5733         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5734             ett_bacapp_tag, NULL,
5735             "%s%d:%02d:%02d.%d %s = %02d:%02d:%02d.%d",
5736             label,
5737             hour > 12 ? hour - 12 : hour,
5738             minute, second, msec,
5739             hour >= 12 ? "P.M." : "A.M.",
5740             hour, minute, second, msec);
5741     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5742
5743     return offset+tag_len+lvt;
5744 }
5745
5746 static guint
5747 fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5748 {
5749     proto_tree *subtree = tree;
5750
5751     if (label != NULL) {
5752         subtree = proto_tree_add_subtree(subtree, tvb, offset, 10, ett_bacapp_value, NULL, label);
5753     }
5754     offset = fDate(tvb, pinfo, subtree, offset, "Date: ");
5755     return fTime(tvb, pinfo, subtree, offset, "Time: ");
5756 }
5757
5758 static guint
5759 fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5760 {
5761     guint lastoffset = 0;
5762     guint8 tag_no, tag_info;
5763     guint32 lvt;
5764
5765     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
5766         lastoffset = offset;
5767         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5768         if (tag_is_closing(tag_info)) {   /* closing Tag, but not for me */
5769             return offset;
5770         }
5771         offset = fTime(tvb, pinfo, tree, offset, "Time: ");
5772         offset = fApplicationTypes(tvb, pinfo, tree, offset, "Value: ");
5773
5774         if (offset == lastoffset) break;    /* exit loop if nothing happens inside */
5775     }
5776     return offset;
5777 }
5778
5779 static guint
5780 fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5781 {
5782     guint8  tag_no, tag_info;
5783     guint32 lvt;
5784
5785     switch (fTagNo(tvb, offset)) {
5786     case 0: /* Date */
5787         offset = fDate(tvb, pinfo, tree, offset, "Date: ");
5788         break;
5789     case 1: /* dateRange */
5790         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5791         offset  = fDateRange(tvb, pinfo, tree, offset);
5792         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5793         break;
5794     case 2: /* BACnetWeekNDay */
5795         offset = fWeekNDay(tvb, pinfo, tree, offset);
5796         break;
5797     default:
5798         return offset;
5799     }
5800
5801     return offset;
5802 }
5803
5804 static guint
5805 fEventTimeStamps( tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
5806 {
5807     guint32     lvt     = 0;
5808     proto_tree* subtree = tree;
5809
5810     if (tvb_reported_length_remaining(tvb, offset) > 0) {
5811         subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventTimeStamps");
5812
5813         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
5814         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
5815         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
5816     }
5817     return offset;
5818 }
5819
5820 static guint
5821 fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5822 {
5823     guint8  tag_no = 0, tag_info = 0;
5824     guint32 lvt    = 0;
5825
5826     if (tvb_reported_length_remaining(tvb, offset) > 0) {   /* don't loop, it's a CHOICE */
5827         switch (fTagNo(tvb, offset)) {
5828         case 0: /* time */
5829             offset = fTime(tvb, pinfo, tree, offset, label?label:"time: ");
5830             break;
5831         case 1: /* sequenceNumber */
5832             offset = fUnsignedTag(tvb, pinfo, tree, offset,
5833                 label?label:"sequence number: ");
5834             break;
5835         case 2: /* dateTime */
5836             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5837             offset  = fDateTime(tvb, pinfo, tree, offset, label?label:"date time: ");
5838             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5839             break;
5840         default:
5841             return offset;
5842         }
5843     }
5844
5845     return offset;
5846 }
5847
5848
5849 static guint
5850 fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5851 {
5852     if (tvb_reported_length_remaining(tvb, offset) > 0) {
5853         offset = fApplicationTypes(tvb, pinfo, tree, offset, "increment: ");
5854     }
5855     return offset;
5856 }
5857
5858 static const value_string
5859 BACnetDaysOfWeek [] = {
5860     { 0, "Monday" },
5861     { 1, "Tuesday" },
5862     { 2, "Wednesday" },
5863     { 3, "Thursday" },
5864     { 4, "Friday" },
5865     { 5, "Saturday" },
5866     { 6, "Sunday" },
5867     { 0, NULL }
5868 };
5869
5870 static guint
5871 fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5872 {
5873     if (tvb_reported_length_remaining(tvb, offset) > 0) {
5874         offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
5875                                              "valid Days: ", BACnetDaysOfWeek);
5876         offset = fTime(tvb, pinfo, tree, offset, "from time: ");
5877         offset = fTime(tvb, pinfo, tree, offset, "to time: ");
5878         offset = fRecipient(tvb, pinfo, tree, offset);
5879         offset = fProcessId(tvb, pinfo, tree, offset);
5880         offset = fApplicationTypes(tvb, pinfo, tree, offset,
5881                                     "issue confirmed notifications: ");
5882         offset = fBitStringTagVS(tvb, pinfo, tree, offset,
5883                                   "transitions: ", BACnetEventTransitionBits);
5884     }
5885     return offset;
5886 }
5887
5888
5889 static guint
5890 fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
5891 {
5892     gchar      *tmp;
5893     guint       start   = offset;
5894     guint8      tag_no, tag_info;
5895     proto_tree *subtree = tree;
5896
5897     offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5898
5899     if (lvt > 0) {
5900         tmp = tvb_bytes_to_str(wmem_packet_scope(), tvb, offset, lvt);
5901         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt,
5902                     ett_bacapp_tag, NULL, "%s %s", label, tmp);
5903         offset += lvt;
5904     }
5905
5906     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
5907
5908     return offset;
5909 }
5910
5911 static guint
5912 fMacAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
5913 {
5914     guint start = offset;
5915     guint8 tag_no, tag_info;
5916     proto_tree* subtree = tree;
5917
5918     offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5919
5920     subtree = proto_tree_add_subtree(tree, tvb, offset, 6, ett_bacapp_tag, NULL, label); /* just add the label, with the tagHeader information in its subtree */
5921
5922     if (lvt > 0) {
5923         if (lvt == 6) { /* we have 6 Byte IP Address with 4 Octets IPv4 and 2 Octets Port Information */
5924
5925             proto_tree_add_item(tree, hf_bacapp_tag_IPV4, tvb, offset, 4, ENC_BIG_ENDIAN);
5926             proto_tree_add_item(tree, hf_bacapp_tag_PORT, tvb, offset+4, 2, ENC_BIG_ENDIAN);
5927
5928         } else {
5929             if (lvt == 18) { /* we have 18 Byte IP Address with 16 Octets IPv6 and 2 Octets Port Information */
5930
5931             proto_tree_add_item(tree, hf_bacapp_tag_IPV6, tvb, offset, 16, ENC_NA);
5932             proto_tree_add_item(tree, hf_bacapp_tag_PORT, tvb, offset+16, 2, ENC_BIG_ENDIAN);
5933
5934             } else { /* we have 1 Byte MS/TP Address or anything else interpreted as an address */
5935                 subtree = proto_tree_add_subtree(tree, tvb, offset, lvt,
5936                     ett_bacapp_tag, NULL, tvb_bytes_to_str(wmem_packet_scope(), tvb, offset, lvt));
5937             }
5938         }
5939         offset += lvt;
5940     }
5941
5942     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
5943
5944     return offset;
5945 }
5946
5947 static guint
5948 fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5949 {
5950     guint8  tag_no, tag_info;
5951     guint32 lvt;
5952     guint   offs;
5953
5954     offset = fUnsignedTag(tvb, pinfo, tree, offset, "network-number");
5955     offs   = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5956     if (lvt == 0) {
5957         proto_tree_add_text(tree, tvb, offset, offs, "MAC-address: broadcast");
5958         offset += offs;
5959     } else
5960         offset  = fMacAddress(tvb, pinfo, tree, offset, "MAC-address: ", lvt);
5961
5962     return offset;
5963 }
5964
5965 static guint
5966 fSessionKey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5967 {
5968     offset = fOctetString(tvb, pinfo, tree, offset, "session key: ", 8);
5969     return fAddress(tvb, pinfo, tree, offset);
5970 }
5971
5972 static guint
5973 fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5974 {
5975     guint8      tag_no, tag_info;
5976     guint32     lvt;
5977     guint       tag_length;
5978     proto_tree *subtree;
5979     guint32     object_id;
5980
5981     tag_length  = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5982     object_id   = tvb_get_ntohl(tvb, offset+tag_length);
5983     object_type = object_id_type(object_id);
5984     subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_length + 4,
5985         ett_bacapp_tag, NULL, "ObjectIdentifier: %s, %u",
5986         val_to_split_str(object_type,
5987             128,
5988             BACnetObjectType,
5989             ASHRAE_Reserved_Fmt,
5990             Vendor_Proprietary_Fmt),
5991         object_id_instance(object_id));
5992
5993     if (col_get_writable(pinfo->cinfo))
5994         col_append_fstr(pinfo->cinfo, COL_INFO, "%s,%u ",
5995             val_to_split_str(object_type,
5996                 128,
5997                 BACnetObjectType,
5998                 ASHRAE_Reserved_Fmt,
5999                 Vendor_Proprietary_Fmt),
6000                 object_id_instance(object_id));
6001
6002     /* update BACnet Statistics */
6003     updateBacnetInfoValue(BACINFO_OBJECTID,
6004                   wmem_strdup(wmem_packet_scope(),
6005                     val_to_split_str(object_type, 128,
6006                     BACnetObjectType, ASHRAE_Reserved_Fmt,
6007                     Vendor_Proprietary_Fmt)));
6008     updateBacnetInfoValue(BACINFO_INSTANCEID,
6009                   wmem_strdup_printf(wmem_packet_scope(),
6010                     "Instance ID: %u",
6011                     object_id_instance(object_id)));
6012
6013     /* here are the details of how we arrived at the above text */
6014     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6015     offset += tag_length;
6016     proto_tree_add_item(subtree, hf_bacapp_objectType, tvb, offset, 4, ENC_BIG_ENDIAN);
6017     proto_tree_add_item(subtree, hf_bacapp_instanceNumber, tvb, offset, 4, ENC_BIG_ENDIAN);
6018     offset += 4;
6019
6020     return offset;
6021 }
6022
6023 static guint
6024 fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6025 {
6026     guint8  tag_no, tag_info;
6027     guint32 lvt;
6028
6029     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6030     if (tag_no < 2) {
6031         if (tag_no == 0) { /* device */
6032             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
6033         }
6034         else {  /* address */
6035             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6036             offset  = fAddress(tvb, pinfo, tree, offset);
6037             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6038         }
6039     }
6040     return offset;
6041 }
6042
6043 static guint
6044 fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6045 {
6046     guint       lastoffset = 0;
6047     guint8      tag_no, tag_info;
6048     guint32     lvt;
6049     proto_tree *orgtree    = tree;
6050     proto_tree *subtree;
6051
6052     /* beginning of new item - indent and label */
6053     tree = proto_tree_add_subtree(orgtree, tvb, offset, 1, ett_bacapp_value, NULL, "Recipient Process" );
6054
6055     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6056         lastoffset = offset;
6057
6058         switch (fTagNo(tvb, offset)) {
6059         case 0: /* recipient */
6060             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
6061             subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "Recipient");    /* add tree label and indent */
6062             offset  = fRecipient(tvb, pinfo, subtree, offset);
6063             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
6064             break;
6065         case 1: /* processId */
6066             offset = fProcessId(tvb, pinfo, tree, offset);
6067             lastoffset = offset;
6068             break;
6069         default:
6070             break;
6071         }
6072         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6073     }
6074     return offset;
6075 }
6076
6077 static guint
6078 fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6079 {
6080     guint       lastoffset = 0;
6081     guint8      tag_no, tag_info;
6082     guint32     lvt;
6083     proto_tree *subtree;
6084     proto_tree *orgtree    = tree;
6085     guint       itemno     = 1;
6086
6087     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6088         lastoffset = offset;
6089         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6090         if (tag_is_closing(tag_info) ) {
6091             return offset;
6092         }
6093         switch (tag_no) {
6094
6095         case 0: /* recipient */
6096                 /* beginning of new item in list */
6097                 tree = proto_tree_add_subtree_format(orgtree, tvb, offset, 1,
6098                     ett_bacapp_value, NULL, "Subscription %d",itemno);    /* add tree label and indent */
6099                 itemno = itemno + 1;
6100
6101                 subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
6102                     ett_bacapp_value, NULL, "Recipient");    /* add tree label and indent */
6103                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
6104                 offset  = fRecipientProcess(tvb, pinfo, subtree, offset);
6105                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);  /* show context close */
6106             break;
6107         case 1: /* MonitoredPropertyReference */
6108                 subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
6109                     ett_bacapp_value, NULL, "Monitored Property Reference");
6110                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6111                 offset  = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
6112                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6113             break;
6114         case 2: /* IssueConfirmedNotifications - boolean */
6115             offset = fBooleanTag(tvb, pinfo, tree, offset, "Issue Confirmed Notifications: ");
6116             break;
6117         case 3: /* TimeRemaining */
6118             offset = fUnsignedTag(tvb, pinfo, tree, offset, "Time Remaining: ");
6119             break;
6120         case 4: /* COVIncrement */
6121             offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
6122             break;
6123         default:
6124             break;
6125         }
6126         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6127     }
6128     return offset;
6129 }
6130
6131 static guint
6132 fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6133 {
6134     offset = fObjectIdentifier(tvb, pinfo, tree, offset);
6135     return fAddress(tvb, pinfo, tree, offset);
6136 }
6137
6138 static guint
6139 fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match)
6140 {
6141     guint       lastoffset = 0, len;
6142     guint8      tag_no, tag_info;
6143     guint32     lvt;
6144     proto_tree *subtree    = tree;
6145
6146     /* set the optional global properties to indicate not-used */
6147     propertyArrayIndex = -1;
6148     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6149         lastoffset = offset;
6150         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6151         if (tag_is_closing(tag_info) ) {
6152             if (tag_no == tag_match) {
6153                 return offset;
6154             }
6155             offset += len;
6156             subtree = tree;
6157             continue;
6158         }
6159         switch (tag_no) {
6160
6161         case 0: /* deviceIdentifier */
6162             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
6163             break;
6164         case 1: /* objectIdentifier */
6165             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
6166             break;
6167         case 2: /* propertyIdentifier */
6168             offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
6169             break;
6170         case 3: /* propertyArrayIndex */
6171             offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
6172             break;
6173         case 4: /* propertyValue */
6174             offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
6175             break;
6176         case 5: /* priority */
6177             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
6178             break;
6179         case 6: /* postDelay */
6180             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Post Delay: ");
6181             break;
6182         case 7: /* quitOnFailure */
6183             offset = fBooleanTag(tvb, pinfo, subtree, offset,
6184                 "Quit On Failure: ");
6185             break;
6186         case 8: /* writeSuccessful */
6187             offset = fBooleanTag(tvb, pinfo, subtree, offset,
6188                 "Write Successful: ");
6189             break;
6190         default:
6191             return offset;
6192         }
6193         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6194     }
6195     return offset;
6196 }
6197
6198 /* BACnetActionList ::= SEQUENCE{
6199       action [0] SEQUENCE OF BACnetActionCommand
6200       }
6201 */
6202 static guint
6203 fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6204 {
6205     guint       lastoffset = 0, len;
6206     guint8      tag_no, tag_info;
6207     guint32     lvt;
6208     proto_tree *subtree    = tree;
6209
6210     while (tvb_reported_length_remaining(tvb, offset) > 0) {
6211         lastoffset = offset;
6212         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6213         if (tag_is_closing(tag_info)) {
6214             subtree = tree;
6215             if ( tag_no != 0 ) /* don't eat the closing property tag, just return */
6216                 return offset;
6217             offset += len;
6218             continue;
6219         }
6220         if (tag_is_opening(tag_info)) {
6221             subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "Action List");
6222             offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
6223                 &tag_no, &tag_info, &lvt);
6224         }
6225         switch (tag_no) {
6226         case 0: /* BACnetActionCommand */
6227             offset = fActionCommand(tvb, pinfo, subtree, offset, tag_no);
6228             break;
6229         default:
6230             break;
6231         }
6232         if (offset == lastoffset) break;    /* nothing happened, exit loop */
6233     }
6234     return offset;
6235 }
6236
6237 static guint
6238 fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6239 {
6240     guint8       tag_no, tag_info;
6241     guint32      lvt;
6242     guint        tag_len;
6243     proto_tree  *subtree;
6244     const gchar *label = "Property Identifier";
6245
6246     propertyIdentifier = 0; /* global Variable */
6247     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6248     /* can we decode this value? */
6249     if (fUnsigned32(tvb, offset+tag_len, lvt, (guint32 *)&propertyIdentifier)) {
6250         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6251             ett_bacapp_tag, NULL,
6252             "%s: %s (%u)", label,
6253             val_to_split_str(propertyIdentifier, 512,
6254                 BACnetPropertyIdentifier,
6255                 ASHRAE_Reserved_Fmt,
6256                 Vendor_Proprietary_Fmt), propertyIdentifier);
6257         if (col_get_writable(pinfo->cinfo))
6258             col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
6259                 val_to_split_str(propertyIdentifier, 512,
6260                     BACnetPropertyIdentifier,
6261                     ASHRAE_Reserved_Fmt,
6262                     Vendor_Proprietary_Fmt));
6263     } else {
6264         /* property identifiers cannot be larger than 22-bits */
6265         return offset;
6266     }
6267
6268     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6269     proto_tree_add_item(subtree, hf_BACnetPropertyIdentifier, tvb,
6270         offset+tag_len, lvt, ENC_BIG_ENDIAN);
6271
6272     return offset+tag_len+lvt;
6273 }
6274
6275 static guint
6276 fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6277 {
6278     guint8      tag_no, tag_info;
6279     guint32     lvt;
6280     guint       tag_len;
6281     proto_tree *subtree;
6282
6283     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6284     if (fUnsigned32(tvb, offset + tag_len, lvt, (guint32 *)&propertyArrayIndex))
6285         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6286             ett_bacapp_tag, NULL, "property Array Index (Unsigned) %u", propertyArrayIndex);
6287     else
6288         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6289             ett_bacapp_tag, NULL, "property Array Index - %u octets (Unsigned)", lvt);
6290     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6291
6292     return offset+tag_len+lvt;
6293 }
6294
6295 static guint
6296 fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6297 {
6298     guint8      tag_no, tag_info, character_set;
6299     guint32     lvt, l;
6300     guint       offs, extra = 1;
6301     const char *coding;
6302     guint8     *out;
6303     proto_tree *subtree;
6304     guint       start = offset;
6305
6306     if (tvb_reported_length_remaining(tvb, offset) > 0) {
6307
6308         offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6309
6310         character_set = tvb_get_guint8(tvb, offset+offs);
6311         /* Account for code page if DBCS */
6312         if (character_set == 1) {
6313             extra = 3;
6314         }
6315         offset += (offs+extra);
6316         lvt -= (extra);
6317
6318         do {
6319             l = MIN(lvt, 256);
6320             /*
6321              * XXX - are we guaranteed that these encoding
6322              * names correspond, on *all* platforms with
6323              * iconv(), to the encodings we want?
6324              * If not (and perhaps even if so), we should
6325              * perhaps have our own iconv() implementation,
6326              * with a different name, so that we control the
6327              * encodings it supports and the names of those
6328              * encodings.
6329              *
6330              * We should also handle that in the general
6331              * string handling code, rather than making it
6332              * specific to the BACAPP dissector, as many
6333              * other dissectors need to handle various
6334              * character encodings.
6335              */
6336             /** this decoding may be not correct for multi-byte characters, Lka */
6337             switch (character_set) {
6338             case ANSI_X3_4:
6339                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_UTF_8);
6340                 coding = "UTF-8";
6341                 break;
6342             case IBM_MS_DBCS:
6343                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_ASCII);
6344                 coding = "IBM MS DBCS";
6345                 break;
6346             case JIS_C_6226:
6347                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_ASCII);
6348                 coding = "JIS C 6226";
6349                 break;
6350             case ISO_10646_UCS4:
6351                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_UCS_4|ENC_BIG_ENDIAN);
6352                 coding = "ISO 10646 UCS-4";
6353                 break;
6354             case ISO_10646_UCS2:
6355                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_UCS_2|ENC_BIG_ENDIAN);
6356                 coding = "ISO 10646 UCS-2";
6357                 break;
6358             case ISO_8859_1:
6359                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_ISO_8859_1);
6360                 coding = "ISO 8859-1";
6361                 break;
6362             default:
6363                 /* Assume this is some form of extended ASCII, with one-byte code points for ASCII characters */
6364                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_ASCII);
6365                 coding = "unknown";
6366                 break;
6367             }
6368             subtree = proto_tree_add_subtree_format(tree, tvb, offset, l, ett_bacapp_tag, NULL,
6369                                         "%s%s '%s'", label, coding, out);
6370             lvt    -= l;
6371             offset += l;
6372         } while (lvt > 0);
6373
6374         fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6375         proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, ENC_BIG_ENDIAN);
6376
6377         if (character_set == 1) {
6378             proto_tree_add_text(subtree, tvb, start+offs+1, 2, "Code Page: %d", tvb_get_ntohs(tvb, start+offs+1));
6379         }
6380         /* XXX - put the string value here */
6381     }
6382     return offset;
6383 }
6384
6385 static guint
6386 fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label,
6387     const value_string *src)
6388 {
6389     guint8      tag_no, tag_info, tmp;
6390     gint        j, unused, skip;
6391     guint       start = offset;
6392     guint       offs;
6393     guint32     lvt, i, numberOfBytes;
6394     guint8      bf_arr[256];
6395     proto_tree* subtree = tree;
6396
6397     offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6398     numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
6399     offset += offs;
6400     unused  = tvb_get_guint8(tvb, offset); /* get the unused Bits */
6401     subtree = proto_tree_add_subtree_format(tree, tvb, start, offs+lvt,
6402                                   ett_bacapp_tag, NULL,
6403                                   "%s(Bit String)", label);
6404
6405     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6406     proto_tree_add_text(subtree, tvb, offset, 1,
6407                 "Unused bits: %u", unused);
6408     memset(bf_arr, 0, 256);
6409     skip = 0;
6410     for (i = 0; i < numberOfBytes; i++) {
6411         tmp = tvb_get_guint8(tvb, (offset)+i+1);
6412         if (i == numberOfBytes-1) { skip = unused; }
6413         for (j = 0; j < 8-skip; j++) {
6414             if (src != NULL) {
6415                 if (tmp & (1 << (7 - j)))
6416                     proto_tree_add_text(subtree, tvb,
6417                         offset+i+1, 1,
6418                         "%s = TRUE",
6419                         val_to_str((guint) (i*8 +j),
6420                             src,
6421                             ASHRAE_Reserved_Fmt));
6422                 else
6423                     proto_tree_add_text(subtree, tvb,
6424                         offset+i+1, 1,
6425                         "%s = FALSE",
6426                         val_to_str((guint) (i*8 +j),
6427                             src,
6428                             ASHRAE_Reserved_Fmt));
6429             } else {
6430                 bf_arr[MIN(255, (i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
6431             }
6432         }
6433     }
6434
6435     if (src == NULL) {
6436         bf_arr[MIN(255, numberOfBytes*8-unused)] = 0;
6437         proto_tree_add_text(subtree, tvb, offset, lvt, "B'%s'", bf_arr);
6438     }
6439
6440     offset += lvt;
6441
6442     return offset;
6443 }
6444
6445 static guint
6446 fBitStringTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6447 {
6448     return fBitStringTagVS(tvb, pinfo, tree, offset, label, NULL);
6449 }
6450
6451 /* handles generic application types, as well as enumerated and enumerations
6452    with reserved and proprietarty ranges (split) */
6453 static guint
6454 fApplicationTypesEnumeratedSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
6455     const gchar *label, const value_string *src, guint32 split_val)
6456 {
6457     guint8  tag_no, tag_info;
6458     guint32 lvt;
6459     guint   tag_len;
6460
6461     if (tvb_reported_length_remaining(tvb, offset) > 0) {
6462
6463         tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6464         if (!tag_is_context_specific(tag_info)) {
6465             switch (tag_no) {
6466             case 0: /** NULL 20.2.2 */
6467                 offset = fNullTag(tvb, pinfo, tree, offset, label);
6468                 break;
6469             case 1: /** BOOLEAN 20.2.3 */
6470                 offset = fBooleanTag(tvb, pinfo, tree, offset, label);
6471                 break;
6472             case 2: /** Unsigned Integer 20.2.4 */
6473                 offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
6474                 break;
6475             case 3: /** Signed Integer 20.2.5 */
6476                 offset = fSignedTag(tvb, pinfo, tree, offset, label);
6477                 break;
6478             case 4: /** Real 20.2.6 */
6479                 offset = fRealTag(tvb, pinfo, tree, offset, label);
6480                 break;
6481             case 5: /** Double 20.2.7 */
6482                 offset = fDoubleTag(tvb, pinfo, tree, offset, label);
6483                 break;
6484             case 6: /** Octet String 20.2.8 */
6485                 offset = fOctetString(tvb, pinfo, tree, offset, label, lvt);
6486                 break;
6487             case 7: /** Character String 20.2.9 */
6488                 offset = fCharacterString(tvb, pinfo, tree, offset, label);
6489                 break;
6490             case 8: /** Bit String 20.2.10 */
6491                 offset = fBitStringTagVS(tvb, pinfo, tree, offset, label, src);
6492                 break;
6493             case 9: /** Enumerated 20.2.11 */
6494                 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, src, split_val);
6495                 break;
6496             case 10: /** Date 20.2.12 */
6497                 offset = fDate(tvb, pinfo, tree, offset, label);
6498                 break;
6499             case 11: /** Time 20.2.13 */
6500                 offset = fTime(tvb, pinfo, tree, offset, label);
6501                 break;
6502             case 12: /** BACnetObjectIdentifier 20.2.14 */
6503                 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
6504                 break;
6505             case 13: /* reserved for ASHRAE */
6506             case 14:
6507             case 15:
6508                 proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s'reserved for ASHRAE'", label);
6509                 offset += lvt + tag_len;
6510                 break;
6511             default:
6512                 break;
6513             }
6514
6515         }
6516     }
6517     return offset;
6518 }
6519
6520 static guint
6521 fShedLevel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6522 {
6523     guint lastoffset = 0;
6524
6525     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6526         lastoffset = offset;
6527
6528         switch (fTagNo(tvb, offset)) {
6529         case 0: /* percent */
6530             offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed percent: ");
6531             break;
6532         case 1: /* level */
6533             offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed level: ");
6534             break;
6535         case 2: /* amount */
6536             offset = fRealTag(tvb, pinfo, tree, offset, "shed amount: ");
6537             break;
6538         default:
6539             return offset;
6540         }
6541         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6542     }
6543     return offset;
6544 }
6545
6546 static guint
6547 fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
6548     const gchar *label, const value_string *vs)
6549 {
6550     return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, vs, 0);
6551 }
6552
6553 static guint
6554 fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
6555     const gchar *label)
6556 {
6557     return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, NULL, 0);
6558 }
6559
6560 static guint
6561 fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6562 {
6563     guint8      tag_no, tag_info;
6564     guint32     lvt;
6565     guint       tag_len;
6566     proto_tree *subtree;
6567     gint        tvb_len;
6568
6569     (void)label;
6570     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6571     /* cap the the suggested length in case of bad data */
6572     tvb_len = tvb_reported_length_remaining(tvb, offset+tag_len);
6573     if ((tvb_len >= 0) && ((guint32)tvb_len < lvt)) {
6574         lvt = tvb_len;
6575     }
6576     subtree = proto_tree_add_subtree_format(tree, tvb, offset+tag_len, lvt,
6577         ett_bacapp_tag, NULL, "Context Value (as %u DATA octets)", lvt);
6578
6579     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6580
6581     return offset + tag_len + lvt;
6582 }
6583 /*
6584 BACnetPrescale ::= SEQUENCE {
6585     multiplier  [0] Unsigned,
6586 moduloDivide    [1] Unsigned
6587 }
6588 */
6589 static guint
6590 fPrescale(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
6591 {
6592     guint8  tag_no, tag_info;
6593     guint32 lvt;
6594     guint   lastoffset = 0;
6595
6596     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6597         lastoffset = offset;
6598         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6599         if (tag_is_closing(tag_info) ) {
6600             return offset;
6601             }
6602         switch (tag_no) {
6603         case 0: /* multiplier */
6604             offset = fUnsignedTag(tvb, pinfo, tree, offset, "Multiplier: ");
6605             break;
6606         case 1: /* moduloDivide */
6607             offset = fUnsignedTag(tvb, pinfo, tree, offset, "Modulo Divide: ");
6608             break;
6609         default:
6610             return offset;
6611         }
6612         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6613     }
6614     return offset;
6615
6616 }
6617 /*
6618 BACnetScale ::= CHOICE {
6619     floatScale  [0] REAL,
6620 integerScale    [1] INTEGER
6621 }
6622 */
6623 static guint
6624 fScale(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
6625 {
6626     guint8  tag_no, tag_info;
6627     guint32 lvt;
6628     guint   lastoffset = 0;
6629
6630     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6631         lastoffset = offset;
6632         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6633         if (tag_is_closing(tag_info) ) {
6634             return offset;
6635             }
6636         switch (tag_no) {
6637         case 0: /* floatScale */
6638             offset = fRealTag(tvb, pinfo, tree, offset, "Float Scale: ");
6639             break;
6640         case 1: /* integerScale */
6641             offset = fSignedTag(tvb, pinfo, tree, offset, "Integer Scale: ");
6642             break;
6643         default:
6644             return offset;
6645         }
6646         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6647     }
6648     return offset;
6649 }
6650 /*
6651 BACnetAccumulatorRecord ::= SEQUENCE {
6652     timestamp       [0] BACnetDateTime,
6653     presentValue        [1] Unsigned,
6654     accumulatedValue    [2] Unsigned,
6655     accumulatortStatus  [3] ENUMERATED {
6656                     normal          (0),
6657                     starting        (1),
6658                     recovered       (2),
6659                     abnormal        (3),
6660                     failed          (4)
6661                     }
6662 }
6663 */
6664 static guint
6665 fLoggingRecord(tvbuff_t *tvb, packet_info *pinfo  _U_, proto_tree *tree, guint offset)
6666 {
6667     guint8  tag_no, tag_info;
6668     guint32 lvt;
6669     guint   lastoffset = 0;
6670
6671     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6672         lastoffset = offset;
6673         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6674         if (tag_is_closing(tag_info) ) {
6675             return offset;
6676             }
6677         switch (tag_no) {
6678         case 0: /* timestamp */
6679             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6680             offset  = fDateTime(tvb, pinfo, tree, offset, "Timestamp: ");
6681             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6682             break;
6683         case 1: /* presentValue */
6684             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Present Value: ");
6685             break;
6686         case 2: /* accumulatedValue */
6687             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Accumulated Value: ");
6688             break;
6689         case 3: /* accumulatorStatus */
6690             offset  = fEnumeratedTag(tvb, pinfo, tree, offset, "Accumulator Status: ", BACnetAccumulatorStatus);
6691             break;
6692         default:
6693             return offset;
6694         }
6695         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6696     }
6697     return offset;
6698 }
6699
6700 /*
6701  SEQ OF Any enumeration (current usage is SEQ OF BACnetDoorAlarmState
6702 */
6703 static guint
6704 fSequenceOfEnums(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, const value_string *vs)
6705 {
6706     guint8  tag_no, tag_info;
6707     guint32 lvt;
6708     guint   lastoffset = 0;
6709
6710     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6711         lastoffset = offset;
6712         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6713         if (tag_is_closing(tag_info) ) {
6714             return offset;
6715             }
6716         offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, label, vs);
6717         if ( offset == lastoffset ) break;
6718     }
6719     return offset;
6720 }
6721
6722 /*
6723 SEQ OF BACnetDeviceObjectReference (accessed as an array)
6724 }
6725 */
6726 static guint
6727 fDoorMembers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6728 {
6729     guint8  tag_no, tag_info;
6730     guint32 lvt;
6731     guint   lastoffset = 0;
6732
6733     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6734         lastoffset = offset;
6735         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6736         if (tag_is_closing(tag_info) ) {
6737             return offset;
6738             }
6739         offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
6740         if (offset == lastoffset) break;
6741     }
6742     return offset;
6743 }
6744
6745 /*
6746 SEQ OF ReadAccessSpecification
6747 */
6748 static guint
6749 fListOfGroupMembers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6750 {
6751     guint8  tag_no, tag_info;
6752     guint32 lvt;
6753     guint   lastoffset = 0;
6754
6755     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6756         lastoffset = offset;
6757         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6758         if (tag_is_closing(tag_info) ) {
6759             return offset;
6760             }
6761         offset = fReadAccessSpecification(tvb, pinfo, tree, offset);
6762         if ( offset == lastoffset ) break;
6763     }
6764     return offset;
6765 }
6766
6767 static guint
6768 fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6769 {
6770     guint8  tag_no, tag_info;
6771     guint32 lvt;
6772     guint   lastoffset = 0, depth = 0;
6773     char    ar[256];
6774     guint32 save_object_type;
6775
6776     if (propertyIdentifier >= 0) {
6777         g_snprintf(ar, sizeof(ar), "%s: ",
6778             val_to_split_str(propertyIdentifier, 512,
6779                 BACnetPropertyIdentifier,
6780                 ASHRAE_Reserved_Fmt,
6781                 Vendor_Proprietary_Fmt));
6782     } else {
6783         g_snprintf(ar, sizeof(ar), "Abstract Type: ");
6784     }
6785     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6786         lastoffset = offset;
6787         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6788         if (tag_is_closing(tag_info)) { /* closing tag, but not for me */
6789             if (depth <= 0) return offset;
6790         }
6791
6792         /* Application Tags */
6793         switch (propertyIdentifier) {
6794         case 2: /* action */
6795             /* loop object is application tagged,
6796                 command object is context tagged */
6797             if (tag_is_context_specific(tag_info)) {
6798                 /* BACnetActionList */
6799                 offset = fActionList(tvb, pinfo, tree, offset);
6800             } else {
6801                 /* BACnetAction */
6802                 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6803                     BACnetAction);
6804             }
6805             break;
6806         case 30: /* BACnetAddressBinding */
6807             offset = fAddressBinding(tvb, pinfo, tree, offset);
6808             break;
6809         case 54: /* list of object property reference */
6810             offset = fLOPR(tvb, pinfo, tree, offset);
6811             break;
6812         case 55: /* list-of-session-keys */
6813             fSessionKey(tvb, pinfo, tree, offset);
6814             break;
6815         case 79: /* object-type */
6816         case 96: /* protocol-object-types-supported */
6817             offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar,
6818                 BACnetObjectType, 128);
6819             break;
6820         case 97: /* Protocol-Services-Supported */
6821             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6822                 BACnetServicesSupported);
6823             break;
6824         case 102: /* recipient-list */
6825             offset = fDestination(tvb, pinfo, tree, offset);
6826             break;
6827         case 107: /* segmentation-supported */
6828             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6829                 BACnetSegmentation);
6830             break;
6831         case 111: /* Status-Flags */
6832             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6833                 BACnetStatusFlags);
6834             break;
6835         case 112: /* System-Status */
6836             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6837                 BACnetDeviceStatus);
6838             break;
6839         case 117: /* units */
6840             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6841                 BACnetEngineeringUnits);
6842             break;
6843         case 87:    /* priority-array -- accessed as a BACnetARRAY */
6844             if (propertyArrayIndex == 0) {
6845                 /* BACnetARRAY index 0 refers to the length
6846                 of the array, not the elements of the array */
6847                 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6848             } else {
6849                 offset = fPriorityArray(tvb, pinfo, tree, offset);
6850             }
6851             break;
6852         case 38:    /* exception-schedule */
6853             if (object_type < 128) {
6854                 if (propertyArrayIndex == 0) {
6855                     /* BACnetARRAY index 0 refers to the length
6856                     of the array, not the elements of the array */
6857                     offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6858                 } else {
6859                     offset = fSpecialEvent(tvb, pinfo, tree, offset);
6860                 }
6861             }
6862             break;
6863         case 19:  /* controlled-variable-reference */
6864         case 60:  /* manipulated-variable-reference */
6865         case 132: /* log-device-object-property */
6866             offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
6867             break;
6868         case 109: /* Setpoint-Reference */
6869             /* setpoint-Reference is actually BACnetSetpointReference which is a SEQ of [0] */
6870             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6871             offset = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
6872             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6873             break;
6874         case 123:   /* weekly-schedule -- accessed as a BACnetARRAY */
6875             if (object_type < 128) {
6876                 if (propertyArrayIndex == 0) {
6877                     /* BACnetARRAY index 0 refers to the length
6878                     of the array, not the elements of the array */
6879                     offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6880                 } else {
6881                     offset = fWeeklySchedule(tvb, pinfo, tree, offset);
6882                 }
6883             }
6884             break;
6885         case 127:   /* client COV increment */
6886             offset = fClientCOV(tvb, pinfo, tree, offset);
6887             break;
6888         case 131:  /* log-buffer */
6889             if ( object_type == 25 )
6890                 offset = fEventLogRecord(tvb, pinfo, tree, offset);
6891             else if ( object_type == 27 )
6892                 offset = fLogMultipleRecord(tvb, pinfo, tree, offset);
6893             else
6894                 offset = fLogRecord(tvb, pinfo, tree, offset);
6895             break;
6896         case 159: /* member-of */
6897         case 165: /* zone-members */
6898             offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
6899             break;
6900         case 196: /* last-restart-reason */
6901             offset = fRestartReason(tvb, pinfo, tree, offset);
6902             break;
6903         case 212: /* actual-shed-level */
6904         case 214: /* expected-shed-level */
6905         case 218: /* requested-shed-level */
6906             offset = fShedLevel(tvb, pinfo, tree, offset);
6907             break;
6908         case 152: /* active-cov-subscriptions */
6909             offset = fCOVSubscription(tvb, pinfo, tree, offset);
6910             break;
6911         case 23: /* date-list */
6912             offset = fCalendarEntry(tvb, pinfo, tree, offset);
6913             break;
6914         case 116: /* time-sychronization-recipients */
6915             offset = fRecipient(tvb, pinfo, tree, offset);
6916             break;
6917         case 83: /* event-parameters */
6918             offset = fEventParameter(tvb, pinfo, tree, offset);
6919             break;
6920         case 211: /* subordinate-list */
6921             offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
6922             break;
6923         case 130: /* event-time-stamp */
6924             offset = fEventTimeStamps(tvb, pinfo, tree, offset);
6925             break;
6926         case 197: /* logging-type */
6927             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLoggingType);
6928             break;
6929         case 36: /* event-state */
6930             offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar, BACnetEventState, 64);
6931             break;
6932         case 103: /* reliability */
6933             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetReliability);
6934             break;
6935         case 72: /* notify-type */
6936             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNotifyType);
6937             break;
6938         case 208: /* node-type */
6939             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNodeType);
6940             break;
6941         case 231: /* door-status */
6942             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorStatus);
6943             break;
6944         case 233: /* lock-status */
6945             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLockStatus);
6946             break;
6947         case 235: /* secured-status */
6948             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorSecuredStatus);
6949             break;
6950         case 158: /* maintenance-required */
6951             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetMaintenance);
6952             break;
6953         case 92: /* program-state */
6954             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramState);
6955             break;
6956         case 90: /* program-change */
6957             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramRequest);
6958             break;
6959         case 100: /* reason-for-halt */
6960             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramError);
6961             break;
6962         case 160: /* mode */
6963             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyMode);
6964             break;
6965         case 163: /* silenced */
6966             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetSilencedState);
6967             break;
6968         case 161: /* operation-expected */
6969             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyOperation);
6970             break;
6971         case 164: /* tracking-value */
6972             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
6973             break;
6974         case 41: /* file-access-method */
6975             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetFileAccessMethod);
6976             break;
6977         case 185:  /* prescale */
6978             offset = fPrescale(tvb, pinfo, tree, offset);
6979             break;
6980         case 187:  /* scale */
6981             offset = fScale(tvb, pinfo, tree, offset);
6982             break;
6983         case 184: /* logging-record */
6984             offset = fLoggingRecord(tvb, pinfo, tree, offset);
6985             break;
6986         case 228: /* door-members */
6987             offset = fDoorMembers(tvb, pinfo, tree, offset);
6988             break;
6989         case 181: /* input-reference */
6990             offset = fObjectPropertyReference(tvb, pinfo, tree, offset);
6991             break;
6992         case 78: /* object-property-reference */
6993             offset = fObjectPropertyReference(tvb, pinfo, tree, offset);
6994             break;
6995         case 234: /* masked-alarm-values */
6996             offset = fSequenceOfEnums(tvb, pinfo, tree, offset, "masked-alarm-value: ", BACnetDoorAlarmState);
6997             break;
6998         case 53:    /* list-of-group-members */
6999             save_object_type = object_type;
7000             offset = fListOfGroupMembers(tvb, pinfo, tree, offset);
7001             object_type = save_object_type;
7002             break;
7003         case 85:    /* present-value */
7004             if ( object_type == 11 )    /* group object handling of present-value */
7005             {
7006                 offset = fReadAccessResult(tvb, pinfo, tree, offset);
7007                 break;
7008             }
7009             /* intentially fall through here so don't reorder this case statement */
7010         default:
7011             if (tag_info) {
7012                 if (tag_is_opening(tag_info)) {
7013                     ++depth;
7014                     offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7015                 } else if (tag_is_closing(tag_info)) {
7016                     --depth;
7017                     offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7018                 } else {
7019                     offset  = fContextTaggedValue(tvb, pinfo, tree, offset, ar);
7020                 }
7021             } else {
7022                 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
7023             }
7024             break;
7025         }
7026         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7027     }
7028     return offset;
7029
7030 }
7031
7032 static guint
7033 fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_info)
7034 {
7035     guint8  tag_no;
7036     guint32 lvt;
7037
7038     if (tag_is_opening(tag_info)) {
7039         offset += fTagHeaderTree(tvb, pinfo, tree, offset,
7040                                  &tag_no, &tag_info, &lvt);
7041         offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
7042         if (tvb_reported_length_remaining(tvb, offset) > 0) {
7043             offset += fTagHeaderTree(tvb, pinfo, tree, offset,
7044                                      &tag_no, &tag_info, &lvt);
7045         }
7046     } else {
7047         proto_tree_add_text(tree, tvb, offset, tvb_reported_length(tvb) - offset,
7048                             "expected Opening Tag!");
7049         offset = tvb_reported_length(tvb);
7050     }
7051
7052     return offset;
7053 }
7054
7055
7056 static guint
7057 fPropertyIdentifierValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset)
7058 {
7059     guint   lastoffset = offset;
7060     guint8  tag_no, tag_info;
7061     guint32 lvt;
7062
7063     offset = fPropertyReference(tvb, pinfo, tree, offset, tagoffset, 0);
7064     if (offset > lastoffset) {
7065         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7066         if (tag_no == tagoffset+2) {  /* Value - might not be present in ReadAccessResult */
7067             offset = fPropertyValue(tvb, pinfo, tree, offset, tag_info);
7068         }
7069     }
7070     return offset;
7071 }
7072
7073 static guint
7074 fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7075 {
7076     guint   lastoffset = 0;
7077     guint8  tag_no, tag_info;
7078     guint32 lvt;
7079
7080     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7081         lastoffset = offset;
7082         offset = fPropertyIdentifierValue(tvb, pinfo, tree, offset, 0);
7083         if (offset > lastoffset) {
7084             /* detect optional priority
7085             by looking to see if the next tag is context tag number 3 */
7086             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7087             if (tag_is_context_specific(tag_info) && (tag_no == 3))
7088                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
7089         }
7090         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7091     }
7092     return offset;
7093 }
7094
7095 static guint
7096 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7097 {
7098     guint       lastoffset = 0, len;
7099     guint8      tag_no, tag_info;
7100     guint32     lvt;
7101     proto_tree *subtree = tree;
7102
7103     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7104         lastoffset = offset;
7105         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7106         if (tag_is_closing(tag_info)) {
7107             offset += len;
7108             subtree = tree;
7109             continue;
7110         }
7111
7112         switch (tag_no) {
7113         case 0: /* ProcessId */
7114             offset = fUnsignedTag(tvb, pinfo, tree, offset, "subscriber Process Id: ");
7115             break;
7116         case 1: /* monitored ObjectId */
7117             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7118             break;
7119         case 2: /* issueConfirmedNotifications */
7120             offset = fBooleanTag(tvb, pinfo, tree, offset, "issue Confirmed Notifications: ");
7121             break;
7122         case 3: /* life time */
7123             offset = fTimeSpan(tvb, pinfo, tree, offset, "life time");
7124             break;
7125         case 4: /* monitoredPropertyIdentifier */
7126             if (tag_is_opening(tag_info)) {
7127                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "monitoredPropertyIdentifier");
7128                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7129                 offset  = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
7130                 break;
7131             }
7132             FAULT;
7133             break;
7134         case 5: /* covIncrement */
7135             offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
7136             break;
7137         default:
7138             return offset;
7139         }
7140         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7141     }
7142     return offset;
7143 }
7144
7145 static guint
7146 fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7147 {
7148     return fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
7149 }
7150
7151 static guint
7152 fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7153 {
7154     guint lastoffset = 0;
7155
7156     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7157         lastoffset = offset;
7158
7159         switch (fTagNo(tvb, offset)) {
7160         case 0: /* deviceInstanceLowLimit */
7161             offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance Low Limit: ");
7162             break;
7163         case 1: /* deviceInstanceHighLimit */
7164             offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance High Limit: ");
7165             break;
7166         case 2: /* BACnetObjectId */
7167             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7168             break;
7169         case 3: /* messageText */
7170             offset = fCharacterString(tvb, pinfo, tree, offset, "Object Name: ");
7171             break;
7172         default:
7173             return offset;
7174         }
7175         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7176     }
7177     return offset;
7178 }
7179
7180
7181 static guint
7182 fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
7183 {
7184     guint   lastoffset = 0;
7185     guint8  tag_no, tag_info;
7186     guint32 lvt;
7187
7188     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7189     if (tag_is_opening(tag_info) && tag_no == 0) {
7190         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* opening context tag 0 */
7191         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7192             lastoffset = offset;
7193             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7194             if (tag_is_closing(tag_info)) {
7195                 /* should be closing context tag 0 */
7196                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7197                 return offset;
7198             }
7199
7200             offset = fTimeValue(tvb, pinfo, subtree, offset);
7201             if (offset == lastoffset) break;    /* nothing happened, exit loop */
7202         }
7203     } else if ((tag_no == 0) && (lvt == 0)) {
7204         /* not sure null (empty array element) is legal */
7205         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7206     }
7207     return offset;
7208 }
7209
7210 static guint
7211 fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7212 {
7213     guint       lastoffset = 0;
7214     guint8      tag_no, tag_info;
7215     guint32     lvt;
7216     guint       i = 1; /* day of week array index */
7217     proto_tree *subtree = tree;
7218
7219     if (propertyArrayIndex > 0) {
7220         /* BACnetARRAY index 0 refers to the length
7221         of the array, not the elements of the array.
7222         BACnetARRAY index -1 is our internal flag that
7223         the optional index was not used.
7224         BACnetARRAY refers to this as all elements of the array.
7225         If the optional index is specified for a BACnetARRAY,
7226         then that specific array element is referenced. */
7227         i = propertyArrayIndex;
7228     }
7229     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7230         lastoffset = offset;
7231         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7232         if (tag_is_closing(tag_info)) {
7233             return offset; /* outer encoding will print out closing tag */
7234         }
7235         subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_bacapp_value, NULL,
7236                                 val_to_str(i++, day_of_week, "day of week (%d) not found"));
7237         offset = fDailySchedule(tvb, pinfo, subtree, offset);
7238         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7239     }
7240     return offset;
7241 }
7242
7243
7244 static guint
7245 fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7246 {
7247     if (tvb_reported_length_remaining(tvb, offset) <= 0)
7248         return offset;
7249
7250     return fDateTime(tvb, pinfo, tree, offset, "UTC-Time: ");
7251 }
7252
7253 static guint
7254 fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7255 {
7256     if (tvb_reported_length_remaining(tvb, offset) <= 0)
7257         return offset;
7258
7259     return fDateTime(tvb, pinfo, tree, offset, NULL);
7260 }
7261
7262 static guint
7263 fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7264 {
7265     if (tvb_reported_length_remaining(tvb, offset) <= 0)
7266         return offset;
7267     offset = fDate(tvb, pinfo, tree, offset, "Start Date: ");
7268     return fDate(tvb, pinfo, tree, offset, "End Date: ");
7269 }
7270
7271 static guint
7272 fVendorIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7273 {
7274     guint32      val   = 0;
7275     guint8       tag_no, tag_info;
7276     guint32      lvt;
7277     guint        tag_len;
7278     proto_item  *ti;
7279     proto_tree  *subtree;
7280     const gchar *label = "Vendor ID";
7281
7282     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7283     if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
7284         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7285             "%s: %s (%u)",
7286             label,
7287             val_to_str_ext_const(val, &BACnetVendorIdentifiers_ext, "Unknown Vendor"),
7288             val);
7289     else
7290         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7291             "%s - %u octets (Unsigned)", label, lvt);
7292     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7293     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7294
7295     if ((lvt < 1) || (lvt > 2)) { /* vendorIDs >= 1  and <= 2 are supported */
7296         proto_tree_add_expert_format(tree, pinfo, &ei_bacapp_bad_length, tvb, 0, lvt,
7297                                 "Wrong length indicated. Expected 1 or 2, got %u", lvt);
7298         return offset+tag_len+lvt;
7299     }
7300
7301     proto_tree_add_item(subtree, hf_BACnetVendorIdentifier, tvb,
7302         offset+tag_len, lvt, ENC_BIG_ENDIAN);
7303
7304     return offset+tag_len+lvt;
7305 }
7306
7307 static guint
7308 fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7309 {
7310     guint32      val   = 0;
7311     guint8       tag_no, tag_info;
7312     guint32      lvt;
7313     guint        tag_len;
7314     proto_item  *ti;
7315     proto_tree  *subtree;
7316     const gchar *label = "Restart Reason";
7317
7318     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7319     if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
7320         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7321             "%s: %s (%u)", label,
7322             val_to_str_const(val, BACnetRestartReason, "Unknown reason"), val);
7323     else
7324         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7325             "%s - %u octets (Unsigned)", label, lvt);
7326     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7327     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7328
7329     if (lvt != 1) {
7330         proto_tree_add_expert_format(tree, pinfo, &ei_bacapp_bad_length, tvb, 0, lvt,
7331                                 "Wrong length indicated. Expected 1, got %u", lvt);
7332         return offset+tag_len+lvt;
7333     }
7334
7335     proto_tree_add_item(subtree, hf_BACnetRestartReason, tvb,
7336         offset+tag_len, lvt, ENC_BIG_ENDIAN);
7337
7338     return offset+tag_len+lvt;
7339 }
7340
7341 static guint
7342 fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7343 {
7344     guint lastoffset = 0;
7345
7346     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7347         lastoffset = offset;
7348         switch (fTagNo(tvb, offset)) {
7349
7350         case 0: /* textMessageSourceDevice */
7351             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7352             break;
7353         case 1: /* messageClass */
7354             switch (fTagNo(tvb, offset)) {
7355             case 0: /* numeric */
7356                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "message Class: ");
7357                 break;
7358             case 1: /* character */
7359                 offset = fCharacterString(tvb, pinfo, tree, offset, "message Class: ");
7360                 break;
7361             }
7362             break;
7363         case 2: /* messagePriority */
7364             offset = fEnumeratedTag(tvb, pinfo, tree, offset, "message Priority: ",
7365                 BACnetMessagePriority);
7366             break;
7367         case 3: /* message */
7368             offset = fCharacterString(tvb, pinfo, tree, offset, "message: ");
7369             break;
7370         default:
7371             return offset;
7372         }
7373         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7374     }
7375     return offset;
7376 }
7377
7378 static guint
7379 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7380 {
7381     return fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
7382 }
7383
7384 static guint
7385 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7386 {
7387     guint       lastoffset, len;
7388     guint8      tag_no, tag_info;
7389     guint32     lvt;
7390     proto_tree *subtree = tree;
7391     tvbuff_t   *next_tvb;
7392     guint       vendor_identifier = 0;
7393     guint       service_number = 0;
7394
7395     len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7396     fUnsigned32(tvb, offset+len, lvt, &vendor_identifier);
7397     if (col_get_writable(pinfo->cinfo))
7398         col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ", vendor_identifier);
7399     offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
7400
7401     next_tvb = tvb_new_subset_remaining(tvb, offset);
7402     if (dissector_try_uint(bacapp_dissector_table,
7403         vendor_identifier, next_tvb, pinfo, tree)) {
7404         /* we parsed it so skip over length and we are done */
7405         offset += tvb_reported_length(next_tvb);
7406         return offset;
7407     }
7408
7409     /* Not handled by vendor dissector */
7410
7411     /* exit loop if nothing happens inside */
7412     while (tvb_reported_length_remaining(tvb, offset) > 0) {
7413         lastoffset = offset;
7414         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7415         if (tag_is_closing(tag_info)) {
7416             if (tag_no == 2) { /* Make sure it's the expected tag */
7417                 offset += len;
7418                 subtree = tree;
7419                 continue;
7420             } else {
7421                 break; /* End loop if incorrect closing tag */
7422             }
7423         }
7424         switch (tag_no) {
7425
7426             /* vendorID is now parsed above */
7427         case 1: /* serviceNumber */
7428             fUnsigned32(tvb, offset+len, lvt, &service_number);
7429             if (col_get_writable(pinfo->cinfo))
7430                 col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ",   service_number);
7431             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
7432             break;
7433         case 2: /*serviceParameters */
7434             if (tag_is_opening(tag_info)) {
7435                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1,
7436                         ett_bacapp_value, NULL, "service Parameters");
7437                 propertyIdentifier = -1;
7438                 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
7439                 break;
7440             }
7441             FAULT;
7442             break;
7443         default:
7444             return offset;
7445         }
7446         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7447     }
7448
7449     return offset;
7450 }
7451
7452 static guint
7453 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7454 {
7455     return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
7456 }
7457
7458 static guint
7459 fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7460 {
7461     return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
7462 }
7463
7464 static guint
7465 fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
7466 {
7467     guint       lastoffset = 0;
7468     guint8      tag_no, tag_info;
7469     guint32     lvt;
7470     proto_tree *subtree = tree;
7471
7472     if (label != NULL) {
7473         subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, label);
7474     }
7475
7476     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7477         lastoffset = offset;
7478         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7479
7480         switch (tag_no) {
7481         case 0: /* subscriberProcessId */
7482             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "requesting Process Id: ");
7483             break;
7484         case 1: /* requestingSource */
7485             offset = fCharacterString(tvb, pinfo, tree, offset, "requesting Source: ");
7486             break;
7487         case 2: /* request */
7488             offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
7489                 "request: ", BACnetLifeSafetyOperation, 64);
7490             break;
7491         case 3: /* objectId */
7492             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
7493             break;
7494         default:
7495             return offset;
7496         }
7497         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7498     }
7499     return offset;
7500 }
7501
7502 typedef struct _value_string_enum {
7503     const value_string *valstr;
7504 } value_string_enum;
7505
7506 static const value_string_enum
7507 BACnetPropertyStatesEnums[] = {
7508     { NULL },
7509     {BACnetBinaryPV },
7510     {BACnetEventType },
7511     {BACnetPolarity },
7512     {BACnetProgramRequest },
7513     {BACnetProgramState },
7514     {BACnetProgramError },
7515     {BACnetReliability },
7516     {BACnetEventState },
7517     {BACnetDeviceStatus },
7518     {BACnetEngineeringUnits },
7519     { NULL },
7520     {BACnetLifeSafetyMode },
7521     {BACnetLifeSafetyState },
7522     {BACnetRestartReason },
7523     {BACnetDoorAlarmState },
7524     {BACnetAction },
7525     {BACnetDoorSecuredStatus },
7526     {BACnetDoorStatus },
7527     { NULL }, /* {BACnetDoorValue }, */
7528     {BACnetFileAccessMethod },
7529     {BACnetLockStatus },
7530     {BACnetLifeSafetyOperation },
7531     {BACnetMaintenance },
7532     {BACnetNodeType },
7533     {BACnetNotifyType },
7534     { NULL }, /* {BACnetSecurityLevel }, */
7535     {BACnetShedState },
7536     {BACnetSilencedState },
7537     { NULL },
7538     { NULL }, /* {BACnetAccessEvent }, */
7539     { NULL }, /* {BACnetZoneOccupancyState }, */
7540     { NULL }, /* {BACnetAccessCredentialDisableReason }, */
7541     { NULL }, /* {BACnetAccessCredentialDisable }, */
7542     { NULL }, /* {BACnetAuthenticationStatus }, */
7543     { NULL },
7544     { NULL }, /* {BACnetBackupState }, */
7545 };
7546 #define BACnetPropertyStatesEnums_Size 36
7547
7548 static guint
7549 fBACnetPropertyStates(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
7550 {
7551     guint8       tag_no, tag_info;
7552     guint32      lvt;
7553     const gchar* label;
7554
7555     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7556     label = wmem_strdup_printf(wmem_packet_scope(), "%s: ",
7557                                val_to_str_const( tag_no, VALS(BACnetPropertyStates), "Unknown State" ));
7558
7559     switch (tag_no) {
7560     case 0:
7561         offset = fBooleanTag(tvb, pinfo, tree, offset, label);
7562         break;
7563     case 11:
7564         offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
7565         break;
7566     default:
7567         if ( (tag_no > BACnetPropertyStatesEnums_Size) ||
7568             VALS(BACnetPropertyStatesEnums[tag_no].valstr) == NULL)
7569         {
7570             offset = fEnumeratedTag(tvb, pinfo, tree, offset, label, NULL);
7571             /* don't use Abstract type here because it is context tagged and therefore we don't know app type */
7572         }
7573         else
7574         {
7575             offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label,
7576                     VALS(BACnetPropertyStatesEnums[tag_no].valstr), 64);
7577         }
7578         break;
7579     }
7580     return offset;
7581 }
7582
7583
7584 /*
7585 BACnetDeviceObjectPropertyValue ::= SEQUENCE {
7586       deviceIdentifier       [0]      BACnetObjectIdentifier,
7587       objectIdentifier       [1]      BACnetObjectIdentifier,
7588       propertyIdentifier     [2]      BACnetPropertyIdentifier,
7589       arrayIndex             [3]      Unsigned OPTIONAL,
7590       value                  [4]      ABSTRACT-SYNTAX.&Type
7591       }
7592 */
7593 static guint
7594 fDeviceObjectPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7595 {
7596     guint   lastoffset = 0;
7597     guint8  tag_no, tag_info;
7598     guint32 lvt;
7599
7600     while (tvb_reported_length_remaining(tvb, offset) > 0) {
7601         lastoffset = offset;
7602         /* check the tag.  A closing tag means we are done */
7603         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7604         if (tag_is_closing(tag_info)) {
7605             return offset;
7606         }
7607         switch (tag_no) {
7608         case 0: /* deviceIdentifier */
7609             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7610             break;
7611         case 1: /* objectIdentifier */
7612             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7613             break;
7614         case 2: /* propertyIdentifier */
7615             offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
7616             break;
7617         case 3: /* arrayIndex - OPTIONAL */
7618             offset = fUnsignedTag(tvb, pinfo, tree, offset,
7619                 "arrayIndex: ");
7620             break;
7621         case 4: /* value */
7622             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7623             offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
7624             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7625             break;
7626         default:
7627             return offset;
7628         }
7629         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7630     }
7631     return offset;
7632 }
7633
7634 /*
7635 BACnetDeviceObjectPropertyReference ::= SEQUENCE {
7636       objectIdentifier       [0]      BACnetObjectIdentifier,
7637       propertyIdentifier     [1]      BACnetPropertyIdentifier,
7638       propertyArrayIndex     [2]      Unsigned OPTIONAL, -- used only with array datatype
7639                                                                 -- if omitted with an array then
7640                                                                 -- the entire array is referenced
7641       deviceIdentifier       [3]      BACnetObjectIdentifier OPTIONAL
7642       }
7643 */
7644 static guint
7645 fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7646 {
7647     return fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
7648 }
7649
7650 /*
7651 BACnetDeviceObjectPropertyReference ::= SEQUENCE {
7652       objectIdentifier       [0]      BACnetObjectIdentifier,
7653       propertyIdentifier     [1]      BACnetPropertyIdentifier,
7654       propertyArrayIndex     [2]      Unsigned OPTIONAL, -- used only with array datatype
7655                                                                 -- if omitted with an array then
7656                                                                 -- the entire array is referenced
7657       deviceIdentifier       [3]      BACnetObjectIdentifier OPTIONAL
7658       }
7659 */
7660 static guint
7661 fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7662 {
7663     guint   lastoffset = 0;
7664     guint8  tag_no, tag_info;
7665     guint32 lvt;
7666
7667     while (tvb_reported_length_remaining(tvb, offset) > 0) {
7668         lastoffset = offset;
7669         /* check the tag.  A closing tag means we are done */
7670         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7671         if (tag_is_closing(tag_info)) {
7672             return offset;
7673         }
7674         switch (tag_no) {
7675         case 0: /* objectIdentifier */
7676             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7677             break;
7678         case 1: /* propertyIdentifier */
7679             offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
7680             break;
7681         case 2: /* arrayIndex - OPTIONAL */
7682             offset = fUnsignedTag(tvb, pinfo, tree, offset,
7683                 "arrayIndex: ");
7684             break;
7685         case 3: /* deviceIdentifier - OPTIONAL */
7686             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7687             break;
7688         default:
7689             return offset;
7690         }
7691         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7692     }
7693     return offset;
7694 }
7695
7696 static guint
7697 fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7698 {
7699     guint       lastoffset = offset;
7700     guint8      tag_no, tag_info;
7701     guint32     lvt;
7702     proto_tree *subtree = tree;
7703
7704     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7705     subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
7706         ett_bacapp_value, NULL, "notification parameters (%d) %s",
7707         tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
7708     /* Opening tag for parameter choice */
7709     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7710
7711     switch (tag_no) {
7712     case 0: /* change-of-bitstring */
7713         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7714             lastoffset = offset;
7715             switch (fTagNo(tvb, offset)) {
7716             case 0:
7717                 offset = fBitStringTag(tvb, pinfo, subtree, offset,
7718                     "referenced-bitstring: ");
7719                 break;
7720             case 1:
7721                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7722                     "status-flags: ", BACnetStatusFlags);
7723                 lastoffset = offset;
7724                 break;
7725             default:
7726                 break;
7727             }
7728             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7729         }
7730         break;
7731     case 1: /* change-of-state */
7732         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7733             lastoffset = offset;
7734             switch (fTagNo(tvb, offset)) {
7735             case 0:
7736                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7737                 offset  = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
7738                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7739                 break;
7740             case 1:
7741                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7742                     "status-flags: ", BACnetStatusFlags);
7743                 lastoffset = offset;
7744                 break;
7745             default:
7746                 break;
7747             }
7748             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7749         }
7750         break;
7751     case 2: /* change-of-value */
7752         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7753             lastoffset = offset;
7754             switch (fTagNo(tvb, offset)) {
7755             case 0:
7756                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7757                 switch (fTagNo(tvb, offset)) {
7758                 case 0:
7759                     offset = fBitStringTag(tvb, pinfo, subtree, offset,
7760                         "changed-bits: ");
7761                     break;
7762                 case 1:
7763                     offset = fRealTag(tvb, pinfo, subtree, offset,
7764                         "changed-value: ");
7765                     break;
7766                 default:
7767                     break;
7768                 }
7769                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7770                 break;
7771             case 1:
7772                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7773                     "status-flags: ", BACnetStatusFlags);
7774                 lastoffset = offset;
7775                 break;
7776             default:
7777                 break;
7778             }
7779             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7780         }
7781         break;
7782     case 3: /* command-failure */
7783         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7784             lastoffset = offset;
7785             switch (fTagNo(tvb, offset)) {
7786             case 0: /* "command-value: " */
7787                 /* from BACnet Table 13-3,
7788                     Standard Object Property Values Returned in Notifications */
7789                 propertyIdentifier = 85; /* PRESENT_VALUE */
7790                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7791                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
7792                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7793                 break;
7794             case 1:
7795                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7796                     "status-flags: ", BACnetStatusFlags);
7797                 break;
7798             case 2: /* "feedback-value: " */
7799                 propertyIdentifier = 40; /* FEEDBACK_VALUE */
7800                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7801                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
7802                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7803                 lastoffset = offset;
7804                 break;
7805             default:
7806                 break;
7807             }
7808             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7809         }
7810         break;
7811     case 4: /* floating-limit */
7812         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7813             lastoffset = offset;
7814             switch (fTagNo(tvb, offset)) {
7815             case 0:
7816                 offset = fRealTag(tvb, pinfo, subtree, offset, "reference-value: ");
7817                 break;
7818             case 1:
7819                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7820                     "status-flags: ", BACnetStatusFlags);
7821                 break;
7822             case 2:
7823                 offset = fRealTag(tvb, pinfo, subtree, offset, "setpoint-value: ");
7824                 break;
7825             case 3:
7826                 offset = fRealTag(tvb, pinfo, subtree, offset, "error-limit: ");
7827                 lastoffset = offset;
7828                 break;
7829             default:
7830                 break;
7831             }
7832             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7833         }
7834         break;
7835     case 5: /* out-of-range */
7836         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7837             lastoffset = offset;
7838             switch (fTagNo(tvb, offset)) {
7839             case 0:
7840                 offset = fRealTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
7841                 break;
7842             case 1:
7843                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7844                     "status-flags: ", BACnetStatusFlags);
7845                 break;
7846             case 2:
7847                 offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
7848                 break;
7849             case 3:
7850                 offset = fRealTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
7851                 lastoffset = offset;
7852                 break;
7853             default:
7854                 break;
7855             }
7856             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7857         }
7858         break;
7859     case 6:
7860         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7861             lastoffset = offset;
7862             offset =fBACnetPropertyValue(tvb, pinfo, subtree, offset);
7863             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7864         }
7865         break;
7866     case 7: /* deprecated (was 'buffer-ready', changed and moved to [10]) */
7867         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7868             lastoffset = offset;
7869             switch (fTagNo(tvb, offset)) {
7870             case 0:
7871                 offset = fObjectIdentifier(tvb, pinfo, subtree, offset); /* buffer-device */
7872                 break;
7873             case 1:
7874                 offset = fObjectIdentifier(tvb, pinfo, subtree, offset); /* buffer-object */
7875                 break;
7876             case 2:
7877                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7878                 offset  = fDateTime(tvb, pinfo, subtree, offset, "previous-notification: ");
7879                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7880                 break;
7881             case 3:
7882                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7883                 offset  = fDateTime(tvb, pinfo, subtree, offset, "current-notification: ");
7884                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7885                 lastoffset = offset;
7886                 break;
7887             default:
7888                 break;
7889             }
7890             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7891         }
7892         break;
7893     case 8: /* change-of-life-safety */
7894         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7895             lastoffset = offset;
7896             switch (fTagNo(tvb, offset)) {
7897             case 0:
7898                 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
7899                     "new-state: ", BACnetLifeSafetyState, 256);
7900                 break;
7901             case 1:
7902                 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
7903                     "new-mode: ", BACnetLifeSafetyMode, 256);
7904                 break;
7905             case 2:
7906                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7907                     "status-flags: ", BACnetStatusFlags);
7908                 break;
7909             case 3:
7910                 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
7911                     "operation-expected: ", BACnetLifeSafetyOperation, 64);
7912                 lastoffset = offset;
7913                 break;
7914             default:
7915                 break;
7916             }
7917             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7918         }
7919         break;
7920     case 9: /* extended */
7921         while (tvb_reported_length_remaining(tvb, offset) > 0) {
7922             lastoffset = offset;
7923             switch (fTagNo(tvb, offset)) {
7924             case 0:
7925                 offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
7926                 break;
7927             case 1:
7928                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7929                     "extended-event-type: ");
7930                 break;
7931             case 2: /* parameters */
7932                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7933                 offset  = fApplicationTypes(tvb, pinfo, subtree, offset, "parameters: ");
7934                 offset  = fDeviceObjectPropertyValue(tvb, pinfo, subtree, offset);
7935                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7936                 lastoffset = offset;
7937                 break;
7938             default:
7939                 break;
7940             }
7941             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7942         }
7943         break;
7944     case 10: /* buffer ready */
7945         while (tvb_reported_length_remaining(tvb, offset) > 0) {
7946             lastoffset = offset;
7947             switch (fTagNo(tvb, offset)) {
7948             case 0: /* buffer-property */
7949                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7950                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
7951                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7952                 break;
7953             case 1:
7954                 offset  = fUnsignedTag(tvb, pinfo, subtree, offset,
7955                     "previous-notification: ");
7956                 break;
7957             case 2:
7958                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7959                     "current-notification: ");
7960                 lastoffset = offset;
7961                 break;
7962             default:
7963                 break;
7964             }
7965             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7966         }
7967         break;
7968     case 11: /* unsigned range */
7969         while (tvb_reported_length_remaining(tvb, offset) > 0) {
7970             lastoffset = offset;
7971             switch (fTagNo(tvb, offset)) {
7972             case 0:
7973                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7974                     "exceeding-value: ");
7975                 break;
7976             case 1:
7977                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7978                     "status-flags: ", BACnetStatusFlags);
7979                 break;
7980             case 2:
7981                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7982                     "exceeded-limit: ");
7983                 lastoffset = offset;
7984                 break;
7985             default:
7986                 break;
7987             }
7988             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7989         }
7990         break;
7991         /* 12 reserved */
7992     case 13: /* access-event */
7993         break;
7994     case 14: /* double-out-of-range */
7995         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7996             lastoffset = offset;
7997             switch (fTagNo(tvb, offset)) {
7998             case 0:
7999                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
8000                 break;
8001             case 1:
8002                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8003                     "status-flags: ", BACnetStatusFlags);
8004                 break;
8005             case 2:
8006                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
8007                 break;
8008             case 3:
8009                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
8010                 lastoffset = offset;
8011                 break;
8012             default:
8013                 break;
8014             }
8015             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8016         }
8017         break;
8018     case 15: /* signed-out-of-range */
8019         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8020             lastoffset = offset;
8021             switch (fTagNo(tvb, offset)) {
8022             case 0:
8023                 offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
8024                 break;
8025             case 1:
8026                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8027                     "status-flags: ", BACnetStatusFlags);
8028                 break;
8029             case 2:
8030                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8031                 break;
8032             case 3:
8033                 offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
8034                 lastoffset = offset;
8035                 break;
8036             default:
8037                 break;
8038             }
8039             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8040         }
8041         break;
8042     case 16: /* unsigned-out-of-range */
8043         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8044             lastoffset = offset;
8045             switch (fTagNo(tvb, offset)) {
8046             case 0:
8047                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
8048                 break;
8049             case 1:
8050                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8051                     "status-flags: ", BACnetStatusFlags);
8052                 break;
8053             case 2:
8054                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8055                 break;
8056             case 3:
8057                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
8058                 lastoffset = offset;
8059                 break;
8060             default:
8061                 break;
8062             }
8063             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8064         }
8065         break;
8066     case 17: /* change-of-characterstring */
8067         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8068             lastoffset = offset;
8069             switch (fTagNo(tvb, offset)) {
8070             case 0:
8071                  /* changed-value (CharacterString) */
8072                 offset  = fCharacterString(tvb, pinfo, subtree, offset, "changed-value: ");
8073                 break;
8074             case 1:
8075                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8076                     "status-flags: ", BACnetStatusFlags);
8077                 break;
8078             case 2:
8079                 /* alarm-value (CharacterString) */
8080                 offset  = fCharacterString(tvb, pinfo, subtree, offset, "alarm-value: ");
8081                 lastoffset = offset;
8082                 break;
8083             default:
8084                 break;
8085             }
8086             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8087         }
8088         break;
8089     case 18: /* change-of-status-flags */
8090         while (tvb_reported_length_remaining(tvb, offset) > 0) {
8091             /* exit loop if nothing happens inside */
8092             lastoffset = offset;
8093             switch (fTagNo(tvb, offset)) {
8094             case 0:
8095                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8096                 offset = fApplicationTypesEnumerated(tvb, pinfo, subtree, offset,
8097                     "present-value: ", BACnetStatusFlags);
8098                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8099                 break;
8100             case 1:
8101                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8102                     "referenced-flags: ", BACnetStatusFlags);
8103                 lastoffset = offset;
8104                 break;
8105             default:
8106                 break;
8107             }
8108             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8109         }
8110         break;
8111         /* todo: add new parameters here ... */
8112     default:
8113         offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
8114         break;
8115     }
8116
8117     /* Closing tag for parameter choice */
8118     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8119
8120     return offset;
8121 }
8122
8123 static guint
8124 fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8125 {
8126     guint       lastoffset = offset;
8127     guint8      tag_no, tag_info;
8128     guint32     lvt;
8129     proto_tree *subtree = tree;
8130
8131     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8132     subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
8133         ett_bacapp_value, NULL, "event parameters (%d) %s",
8134         tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
8135
8136     /* Opening tag for parameter choice */
8137     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8138
8139     switch (tag_no) {
8140     case 0: /* change-of-bitstring */
8141         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8142             lastoffset = offset;
8143             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8144             if (tag_is_closing(tag_info)) {
8145                 break;
8146             }
8147             switch (tag_no) {
8148             case 0:
8149                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8150                 break;
8151             case 1:
8152                 offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
8153                 break;
8154             case 2: /* SEQUENCE OF BIT STRING */
8155                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8156                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8157                     lastoffset = offset;
8158                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8159                     if (tag_is_closing(tag_info)) {
8160                         break;
8161                     }
8162                     offset = fBitStringTag(tvb, pinfo, subtree, offset,
8163                                            "bitstring value: ");
8164                 }
8165                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8166                 break;
8167             default:
8168                 break;
8169             }
8170         }
8171         break;
8172     case 1: /* change-of-state */
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             switch (tag_no) {
8180             case 0:
8181                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8182                 break;
8183             case 1: /* SEQUENCE OF BACnetPropertyStates */
8184                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8185                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8186                     lastoffset = offset;
8187                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8188                     if (tag_is_closing(tag_info)) {
8189                         break;
8190                     }
8191                     offset = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
8192                 }
8193                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8194                 break;
8195             default:
8196                 break;
8197             }
8198         }
8199         break;
8200     case 2: /* change-of-value */
8201         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8202             lastoffset = offset;
8203             switch (fTagNo(tvb, offset)) {
8204             case 0:
8205                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8206                 break;
8207             case 1: /* don't loop it, it's a CHOICE */
8208                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8209                 switch (fTagNo(tvb, offset)) {
8210                 case 0:
8211                     offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
8212                     break;
8213                 case 1:
8214                     offset = fRealTag(tvb, pinfo, subtree, offset,
8215                                        "referenced Property Increment: ");
8216                     break;
8217                 default:
8218                     break;
8219                 }
8220                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8221                 break;
8222             default:
8223                 break;
8224             }
8225         }
8226         break;
8227     case 3: /* command-failure */
8228         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8229             lastoffset = offset;
8230             tag_no = fTagNo(tvb, offset);
8231             switch (tag_no) {
8232             case 0:
8233                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8234                 break;
8235             case 1:
8236                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8237                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8238                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8239                 break;
8240             default:
8241                 break;
8242             }
8243         }
8244         break;
8245     case 4: /* floating-limit */
8246         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8247             lastoffset = offset;
8248             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8249             if (tag_is_closing(tag_info)) {
8250                 break;
8251             }
8252             switch (tag_no) {
8253             case 0:
8254                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8255                 break;
8256             case 1:
8257                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8258                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8259                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8260                 break;
8261             case 2:
8262                 offset  = fRealTag(tvb, pinfo, subtree, offset, "low diff limit: ");
8263                 break;
8264             case 3:
8265                 offset  = fRealTag(tvb, pinfo, subtree, offset, "high diff limit: ");
8266                 break;
8267             case 4:
8268                 offset  = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
8269                 break;
8270             default:
8271                 break;
8272             }
8273         }
8274         break;
8275     case 5: /* out-of-range */
8276         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8277             lastoffset = offset;
8278             switch (fTagNo(tvb, offset)) {
8279             case 0:
8280                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8281                 break;
8282             case 1:
8283                 offset = fRealTag(tvb, pinfo, subtree, offset, "low limit: ");
8284                 break;
8285             case 2:
8286                 offset = fRealTag(tvb, pinfo, subtree, offset, "high limit: ");
8287                 break;
8288             case 3:
8289                 offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
8290                 break;
8291             default:
8292                 break;
8293             }
8294         }
8295         break;
8296         /*  deprectated
8297             case 6:
8298             offset = fBACnetPropertyValue (tvb, pinfo, tree, offset);
8299             break;
8300         */
8301
8302     case 7: /* buffer-ready */
8303 #if 0
8304         /* deprecated */
8305         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
8306             lastoffset = offset;
8307             switch (fTagNo(tvb, offset)) {
8308             case 0:
8309                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "notification threshold");
8310                 break;
8311             case 1:
8312                 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8313                                        "previous notification count: ");
8314                 break;
8315             default:
8316                 return offset;
8317             }
8318         }
8319 #endif
8320         break;
8321     case 8: /* change-of-life-safety */
8322         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8323             lastoffset = offset;
8324             switch (fTagNo(tvb, offset)) {
8325             case 0:
8326                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8327                 break;
8328             case 1:
8329                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8330                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8331                     lastoffset = offset;
8332                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8333                     if (tag_is_closing(tag_info)) {
8334                         break;
8335                     }
8336                     offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
8337                                                   "life safety alarm value: ", BACnetLifeSafetyState, 256);
8338                 }
8339                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8340                 break;
8341             case 2:
8342                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8343                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8344                     lastoffset = offset;
8345                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8346                     if (tag_is_closing(tag_info)) {
8347                         break;
8348                     }
8349                     offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
8350                                                   "alarm value: ", BACnetLifeSafetyState, 256);
8351                 }
8352                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8353                 break;
8354             case 3:
8355                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8356                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8357                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8358                 break;
8359             default:
8360                 break;
8361             }
8362         }
8363         break;
8364     case 9: /* extended */
8365         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8366             lastoffset = offset;
8367             switch (fTagNo(tvb, offset)) {
8368             case 0:
8369                 offset = fVendorIdentifier(tvb, pinfo, tree, offset);
8370                 break;
8371             case 1:
8372                 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8373                                        "extended-event-type: ");
8374                 break;
8375             case 2: /* parameters */
8376                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8377                 offset  = fApplicationTypes(tvb, pinfo, tree, offset, "parameters: ");
8378                 offset  = fDeviceObjectPropertyValue(tvb, pinfo, tree, offset);
8379                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8380                 lastoffset = offset;
8381                 break;
8382             default:
8383                 break;
8384             }
8385             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8386         }
8387         break;
8388     case 10: /* buffer-ready */
8389         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8390             lastoffset = offset;
8391             switch (fTagNo(tvb, offset)) {
8392             case 0:
8393                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
8394                                        "notification-threshold: ");
8395                 break;
8396             case 1:
8397                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
8398                                        "previous-notification-count: ");
8399                 break;
8400             default:
8401                 break;
8402             }
8403         }
8404         break;
8405     case 11: /* unsigned-range */
8406         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8407             lastoffset = offset;
8408             switch (fTagNo(tvb, offset)) {
8409             case 0:
8410                 offset = fTimeSpan(tvb, pinfo, tree, offset, "Time Delay");
8411                 break;
8412             case 1:
8413                 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8414                                        "low-limit: ");
8415                 break;
8416             case 2:
8417                 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8418                                        "high-limit: ");
8419                 break;
8420             default:
8421                 break;
8422             }
8423         }
8424         break;
8425     case 13: /* access-event */
8426         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8427             lastoffset = offset;
8428             switch (fTagNo(tvb, offset)) {
8429             case 0:
8430                 /* TODO: [0] SEQUENCE OF BACnetAccessEvent */
8431                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8432                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8433                     lastoffset = offset;
8434                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8435                     if (tag_is_closing(tag_info)) {
8436                         break;
8437                     }
8438                     offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
8439                                                   "access event: ", BACnetAccessEvent, 512);
8440                 }
8441                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8442                 break;
8443             case 1:
8444                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8445                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8446                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8447                 break;
8448             default:
8449                 break;
8450             }
8451         }
8452         break;
8453     case 14: /* double-out-of-range */
8454         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8455             lastoffset = offset;
8456             switch (fTagNo(tvb, offset)) {
8457             case 0:
8458                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8459                 break;
8460             case 1:
8461                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "low limit: ");
8462                 break;
8463             case 2:
8464                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "high limit: ");
8465                 break;
8466             case 3:
8467                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
8468                 break;
8469             default:
8470                 break;
8471             }
8472         }
8473         break;
8474     case 15: /* signed-out-of-range */
8475         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8476             lastoffset = offset;
8477             switch (fTagNo(tvb, offset)) {
8478             case 0:
8479                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8480                 break;
8481             case 1:
8482                 offset = fSignedTag(tvb, pinfo, subtree, offset, "low limit: ");
8483                 break;
8484             case 2:
8485                 offset = fSignedTag(tvb, pinfo, subtree, offset, "high limit: ");
8486                 break;
8487             case 3:
8488                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8489                 break;
8490             default:
8491                 break;
8492             }
8493         }
8494         break;
8495     case 16: /* unsigned-out-of-range */
8496         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8497             lastoffset = offset;
8498             switch (fTagNo(tvb, offset)) {
8499             case 0:
8500                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8501                 break;
8502             case 1:
8503                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "low limit: ");
8504                 break;
8505             case 2:
8506                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "high limit: ");
8507                 break;
8508             case 3:
8509                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8510                 break;
8511             default:
8512                 break;
8513             }
8514         }
8515         break;
8516     case 17: /* change-of-characterstring */
8517         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8518             lastoffset = offset;
8519             switch (fTagNo(tvb, offset)) {
8520             case 0:
8521                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8522                 break;
8523             case 1: /* SEQUENCE OF CharacterString */
8524                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8525                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8526                     lastoffset = offset;
8527                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8528                     if (tag_is_closing(tag_info)) {
8529                         break;
8530                     }
8531                     offset  = fCharacterString(tvb, pinfo, tree, offset, "alarm value: ");
8532                 }
8533                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8534                 break;
8535             default:
8536                 break;
8537             }
8538         }
8539         break;
8540     case 18: /* change-of-status-flags */
8541         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8542             lastoffset = offset;
8543             switch (fTagNo(tvb, offset)) {
8544             case 0:
8545                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8546                 break;
8547             case 1:
8548                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8549                     "selected flags: ", BACnetStatusFlags);
8550                 break;
8551             default:
8552                 break;
8553             }
8554         }
8555         break;
8556         /* todo: add new event-parameter cases here */
8557     default:
8558         break;
8559     }
8560
8561     /* Closing tag for parameter choice */
8562     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8563     return offset;
8564 }
8565
8566 static guint
8567 fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8568 {
8569     guint       lastoffset = 0;
8570     guint8      tag_no, tag_info;
8571     guint32     lvt;
8572     proto_tree *subtree = tree;
8573
8574     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8575         lastoffset = offset;
8576         switch (fTagNo(tvb, offset)) {
8577         case 0: /* timestamp */
8578             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8579             offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
8580             offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
8581             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8582             break;
8583         case 1: /* logDatum: don't loop, it's a CHOICE */
8584             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8585             switch (fTagNo(tvb, offset)) {
8586             case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
8587                 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
8588                 break;
8589             case 1: /* todo: move this to new method fConfirmedEventNotificationRequestTag... */
8590                 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "notification: ");
8591                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8592                 offset  = fConfirmedEventNotificationRequest(tvb, pinfo, subtree, offset);
8593                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8594                 break;
8595             case 2:
8596                 offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
8597                 break;
8598             default:
8599                 return offset;
8600             }
8601             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8602             break;
8603         default:
8604             return offset;
8605         }
8606         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8607     }
8608     return offset;
8609 }
8610
8611 static guint
8612 fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8613 {
8614     guint   lastoffset = 0;
8615     guint8  tag_no, tag_info;
8616     guint32 lvt;
8617
8618     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8619         lastoffset = offset;
8620         switch (fTagNo(tvb, offset)) {
8621         case 0: /* timestamp */
8622             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8623             offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
8624             offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
8625             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8626             break;
8627         case 1: /* logDatum: don't loop, it's a CHOICE */
8628             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8629             switch (fTagNo(tvb, offset)) {
8630             case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
8631                 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
8632                 break;
8633             case 1:
8634                 offset = fBooleanTag(tvb, pinfo, tree, offset, "boolean-value: ");
8635                 break;
8636             case 2:
8637                 offset = fRealTag(tvb, pinfo, tree, offset, "real value: ");
8638                 break;
8639             case 3:
8640                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "enum value: ");
8641                 break;
8642             case 4:
8643                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "unsigned value: ");
8644                 break;
8645             case 5:
8646                 offset = fSignedTag(tvb, pinfo, tree, offset, "signed value: ");
8647                 break;
8648             case 6:
8649                 offset = fBitStringTag(tvb, pinfo, tree, offset, "bitstring value: ");
8650                 break;
8651             case 7:
8652                 offset = fNullTag(tvb, pinfo, tree, offset, "null value: ");
8653                 break;
8654             case 8:
8655                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8656                 offset  = fError(tvb, pinfo, tree, offset);
8657                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8658                 break;
8659             case 9:
8660                 offset = fRealTag(tvb, pinfo, tree, offset, "time change: ");
8661                 break;
8662             case 10:    /* any Value */
8663                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8664                 offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
8665                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8666                 break;
8667             default:
8668                 return offset;
8669             }
8670             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8671             break;
8672         case 2:
8673             /* Changed this to BitString per BACnet Spec. */
8674             offset = fBitStringTagVS(tvb, pinfo, tree, offset, "Status Flags:", BACnetStatusFlags);
8675             break;
8676         default:
8677             return offset;
8678         }
8679         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8680     }
8681     return offset;
8682 }
8683
8684 static guint
8685 fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8686 {
8687     guint   lastoffset = 0;
8688     guint8  tag_no, tag_info;
8689     guint32 lvt;
8690
8691     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8692         lastoffset = offset;
8693         switch (fTagNo(tvb, offset)) {
8694         case 0: /* timestamp */
8695             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8696             offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
8697             offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
8698             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8699             break;
8700         case 1: /* logData: don't loop, it's a CHOICE */
8701             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8702             switch (fTagNo(tvb, offset)) {
8703             case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
8704                 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
8705                 break;
8706             case 1: /* log-data: SEQUENCE OF CHOICE */
8707                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8708                 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset != lastoffset)) {  /* exit loop if nothing happens inside */
8709                     lastoffset = offset;
8710                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8711                     if (tag_is_closing(tag_info)) {
8712                         lastoffset = offset;
8713                         break;
8714                     }
8715                     switch (tag_no) {
8716                     case 0:
8717                         offset = fBooleanTag(tvb, pinfo, tree, offset, "boolean-value: ");
8718                         break;
8719                     case 1:
8720                         offset = fRealTag(tvb, pinfo, tree, offset, "real value: ");
8721                         break;
8722                     case 2:
8723                         offset = fUnsignedTag(tvb, pinfo, tree, offset, "enum value: ");
8724                         break;
8725                     case 3:
8726                         offset = fUnsignedTag(tvb, pinfo, tree, offset, "unsigned value: ");
8727                         break;
8728                     case 4:
8729                         offset = fSignedTag(tvb, pinfo, tree, offset, "signed value: ");
8730                         break;
8731                     case 5:
8732                         offset = fBitStringTag(tvb, pinfo, tree, offset, "bitstring value: ");
8733                         break;
8734                     case 6:
8735                         offset = fNullTag(tvb, pinfo, tree, offset, "null value: ");
8736                         break;
8737                     case 7:
8738                         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8739                         offset  = fError(tvb, pinfo, tree, offset);
8740                         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8741                         break;
8742                     case 8: /* any Value */
8743                         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8744                         offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
8745                         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8746                         break;
8747                     default:
8748                         return offset;
8749                     }
8750                 }
8751                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8752                 break;
8753             case 2:
8754                 offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
8755                 break;
8756             default:
8757                 return offset;
8758             }
8759             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8760             break;
8761         default:
8762             return offset;
8763         }
8764         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8765     }
8766     return offset;
8767 }
8768
8769
8770 static guint
8771 fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8772 {
8773     guint   lastoffset = 0;
8774     guint8  tag_no, tag_info;
8775     guint32 lvt;
8776
8777     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8778         lastoffset = offset;
8779         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8780         if (tag_is_closing(tag_info)) {
8781             break;
8782         }
8783
8784         switch (tag_no) {
8785         case 0: /* ProcessId */
8786             offset  = fProcessId(tvb, pinfo, tree, offset);
8787             break;
8788         case 1: /* initiating ObjectId */
8789             offset  = fObjectIdentifier(tvb, pinfo, tree, offset);
8790             break;
8791         case 2: /* event ObjectId */
8792             offset  = fObjectIdentifier(tvb, pinfo, tree, offset);
8793             break;
8794         case 3: /* time stamp */
8795             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8796             offset  = fTimeStamp(tvb, pinfo, tree, offset, NULL);
8797             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8798             break;
8799         case 4: /* notificationClass */
8800             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
8801             break;
8802         case 5: /* Priority */
8803             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
8804             break;
8805         case 6: /* EventType */
8806             offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8807                 "Event Type: ", BACnetEventType, 64);
8808             break;
8809         case 7: /* messageText */
8810             offset  = fCharacterString(tvb, pinfo, tree, offset, "message Text: ");
8811             break;
8812         case 8: /* NotifyType */
8813             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
8814                 "Notify Type: ", BACnetNotifyType);
8815             break;
8816         case 9: /* ackRequired */
8817             offset  = fBooleanTag(tvb, pinfo, tree, offset, "ack Required: ");
8818             break;
8819         case 10: /* fromState */
8820             offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8821                 "from State: ", BACnetEventState, 64);
8822             break;
8823         case 11: /* toState */
8824             offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8825                 "to State: ", BACnetEventState, 64);
8826             break;
8827         case 12: /* NotificationParameters */
8828             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8829             offset  = fNotificationParameters(tvb, pinfo, tree, offset);
8830             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8831             break;
8832         default:
8833             break;
8834         }
8835         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8836     }
8837     return offset;
8838 }
8839
8840 static guint
8841 fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8842 {
8843     return fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
8844 }
8845
8846 static guint
8847 fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8848 {
8849     guint       lastoffset = 0, len;
8850     guint8      tag_no, tag_info;
8851     guint32     lvt;
8852     proto_tree *subtree    = tree;
8853
8854     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8855         lastoffset = offset;
8856         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8857         if (tag_is_closing(tag_info)) {
8858             offset += len;
8859             subtree = tree;
8860             continue;
8861         }
8862
8863         switch (tag_no) {
8864         case 0: /* ProcessId */
8865             offset = fProcessId(tvb, pinfo, tree, offset);
8866             break;
8867         case 1: /* initiating DeviceId */
8868             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
8869             break;
8870         case 2: /* monitored ObjectId */
8871             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
8872             break;
8873         case 3: /* time remaining */
8874             offset = fTimeSpan(tvb, pinfo, tree, offset, "Time remaining");
8875             break;
8876         case 4: /* List of Values */
8877             if (tag_is_opening(tag_info)) {
8878                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list of Values");
8879                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8880                 offset  = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
8881                 break;
8882             }
8883             FAULT;
8884             break;
8885         default:
8886             return offset;
8887         }
8888         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8889     }
8890     return offset;
8891 }
8892
8893 static guint
8894 fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8895 {
8896     return fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
8897 }
8898
8899 static guint
8900 fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8901 {
8902     guint   lastoffset = 0;
8903     guint8  tag_no = 0, tag_info = 0;
8904     guint32 lvt = 0;
8905
8906     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8907         lastoffset = offset;
8908         switch (fTagNo(tvb, offset)) {
8909         case 0: /* acknowledgingProcessId */
8910             offset = fUnsignedTag(tvb, pinfo, tree, offset, "acknowledging Process Id: ");
8911             break;
8912         case 1: /* eventObjectId */
8913             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
8914             break;
8915         case 2: /* eventStateAcknowledged */
8916             offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8917                 "event State Acknowledged: ", BACnetEventState, 64);
8918             break;
8919         case 3: /* timeStamp */
8920             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8921             offset  = fTimeStamp(tvb, pinfo, tree, offset, NULL);
8922             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8923             break;
8924         case 4: /* acknowledgementSource */
8925             offset  = fCharacterString(tvb, pinfo, tree, offset, "acknowledgement Source: ");
8926             break;
8927         case 5: /* timeOfAcknowledgement */
8928             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8929             offset  = fTimeStamp(tvb, pinfo, tree, offset, "acknowledgement timestamp: ");
8930             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8931             break;
8932         default:
8933             return offset;
8934         }
8935         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8936     }
8937     return offset;
8938 }
8939
8940 static guint
8941 fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8942 {
8943     guint lastoffset = 0;
8944
8945     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8946         lastoffset = offset;
8947         offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
8948         offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
8949             "alarm State: ", BACnetEventState, 64);
8950         offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
8951             "acknowledged Transitions: ", BACnetEventTransitionBits);
8952         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8953     }
8954     return  offset;
8955 }
8956
8957 static guint
8958 fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8959 {
8960     guint   lastoffset = 0;
8961     guint8  tag_no, tag_info;
8962     guint32 lvt;
8963
8964     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8965         lastoffset = offset;
8966         switch (fTagNo(tvb, offset)) {
8967         case 0: /* acknowledgmentFilter */
8968             offset = fEnumeratedTag(tvb, pinfo, tree, offset,
8969                 "acknowledgment Filter: ", BACnetAcknowledgementFilter);
8970             break;
8971         case 1: /* eventObjectId - OPTIONAL */
8972             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8973             offset  = fRecipientProcess(tvb, pinfo, tree, offset);
8974             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8975             break;
8976         case 2: /* eventStateFilter */
8977             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
8978                 "event State Filter: ", BACnetEventStateFilter);
8979             break;
8980         case 3: /* eventTypeFilter - OPTIONAL */
8981             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
8982                 "event Type Filter: ", BACnetEventType);
8983             break;
8984         case 4: /* priorityFilter */
8985             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8986             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "min Priority: ");
8987             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "max Priority: ");
8988             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8989             break;
8990         case 5: /* notificationClassFilter - OPTIONAL */
8991             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "notification Class Filter: ");
8992             break;
8993         default:
8994             return offset;
8995         }
8996         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8997     }
8998     return offset;
8999 }
9000
9001 static guint
9002 fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9003 {
9004     guint lastoffset = 0;
9005
9006     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9007         lastoffset = offset;
9008         offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
9009         offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
9010             "event Type: ", BACnetEventType, 64);
9011         offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
9012             "event State: ", BACnetEventState);
9013         offset = fApplicationTypes(tvb, pinfo, tree, offset, "Priority: ");
9014         if (tvb_reported_length_remaining(tvb, offset) > 0 && fTagNo(tvb, offset) == 2)  /* Notification Class - OPTIONAL */
9015             offset = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
9016         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9017     }
9018
9019     return  offset;
9020 }
9021
9022 static guint
9023 fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9024 {
9025     if (tvb_reported_length_remaining(tvb, offset) > 0) {
9026         if (fTagNo(tvb, offset) == 0) {
9027             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9028         }
9029     }
9030     return offset;
9031 }
9032
9033 static guint
9034 flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9035 {
9036     guint       lastoffset = 0;
9037     guint8      tag_no, tag_info;
9038     guint32     lvt;
9039     proto_tree* subtree = tree;
9040
9041     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9042         lastoffset = offset;
9043         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9044         /* we are finished here if we spot a closing tag */
9045         if (tag_is_closing(tag_info)) {
9046             break;
9047         }
9048         switch (tag_no) {
9049         case 0: /* ObjectId */
9050             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9051             break;
9052         case 1: /* eventState */
9053             offset = fEnumeratedTag(tvb, pinfo, tree, offset,
9054                 "event State: ", BACnetEventState);
9055             break;
9056         case 2: /* acknowledgedTransitions */
9057             offset = fBitStringTagVS(tvb, pinfo, tree, offset,
9058                 "acknowledged Transitions: ", BACnetEventTransitionBits);
9059             break;
9060         case 3: /* eventTimeStamps */
9061             subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventTimeStamps");
9062             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9063             offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
9064             offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
9065             offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
9066             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9067             break;
9068         case 4: /* notifyType */
9069             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
9070                 "Notify Type: ", BACnetNotifyType);
9071             break;
9072         case 5: /* eventEnable */
9073             offset  = fBitStringTagVS(tvb, pinfo, tree, offset,
9074                 "event Enable: ", BACnetEventTransitionBits);
9075             break;
9076         case 6: /* eventPriorities */
9077             subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventPriorities");
9078             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9079             offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-OFFNORMAL Priority: ");
9080             offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-FAULT Priority: ");
9081             offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-NORMAL Priority: ");
9082             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9083             break;
9084         default:
9085             return offset;
9086         }
9087         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9088     }
9089     return offset;
9090 }
9091
9092 static guint
9093 fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9094 {
9095     guint   lastoffset = 0;
9096     guint8  tag_no, tag_info;
9097     guint32 lvt;
9098
9099     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9100     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9101         lastoffset = offset;
9102         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9103         /* we are finished here if we spot a closing tag */
9104         if (tag_is_closing(tag_info)) {
9105             break;
9106         }
9107         offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
9108         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9109     }
9110     return offset;
9111 }
9112
9113 static guint
9114 fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9115 {
9116     guint   lastoffset = 0;
9117     guint8  tag_no, tag_info;
9118     guint32 lvt;
9119
9120     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9121         lastoffset = offset;
9122         switch (fTagNo(tvb, offset)) {
9123         case 0: /* listOfEventSummaries */
9124             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9125             offset  = flistOfEventSummaries(tvb, pinfo, tree, offset);
9126             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9127             break;
9128         case 1: /* moreEvents */
9129             offset  = fBooleanTag(tvb, pinfo, tree, offset, "more Events: ");
9130             break;
9131         default:
9132             return offset;
9133         }
9134         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9135     }
9136     return offset;
9137 }
9138
9139 static guint
9140 fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9141 {
9142     guint       lastoffset = 0, len;
9143     guint8      tag_no, tag_info;
9144     guint32     lvt;
9145     proto_tree *subtree    = tree;
9146
9147     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9148
9149     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9150         lastoffset = offset;
9151         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9152         if (tag_is_closing(tag_info)) {
9153             offset += len;
9154             subtree = tree;
9155             continue;
9156         }
9157
9158         switch (tag_no) {
9159         case 0: /* ObjectId */
9160             offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
9161             break;
9162         case 3: /* listOfElements */
9163             if (tag_is_opening(tag_info)) {
9164                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfElements");
9165                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9166                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
9167                 break;
9168             }
9169             FAULT;
9170             break;
9171         default:
9172             return offset;
9173         }
9174         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9175     }
9176     return offset;
9177 }
9178
9179 static guint
9180 fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9181 {
9182     return fObjectIdentifier(tvb, pinfo, tree, offset);
9183 }
9184
9185 static guint
9186 fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9187 {
9188     guint lastoffset = 0;
9189
9190     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9191         lastoffset = offset;
9192
9193         switch (fTagNo(tvb, offset)) {
9194         case 0: /* timeDuration */
9195             offset = fUnsignedTag(tvb, pinfo, tree, offset, "time Duration: ");
9196             break;
9197         case 1: /* enable-disable */
9198             offset = fEnumeratedTag(tvb, pinfo, tree, offset, "enable-disable: ",
9199                 BACnetEnableDisable);
9200             break;
9201         case 2: /* password - OPTIONAL */
9202             offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
9203             break;
9204         default:
9205             return offset;
9206         }
9207         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9208     }
9209     return offset;
9210 }
9211
9212 static guint
9213 fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9214 {
9215     guint lastoffset = 0;
9216
9217     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9218         lastoffset = offset;
9219
9220         switch (fTagNo(tvb, offset)) {
9221         case 0: /* reinitializedStateOfDevice */
9222             offset = fEnumeratedTag(tvb, pinfo, tree, offset,
9223                 "reinitialized State Of Device: ",
9224                 BACnetReinitializedStateOfDevice);
9225             break;
9226         case 1: /* password - OPTIONAL */
9227             offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
9228             break;
9229         default:
9230             return offset;
9231         }
9232         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9233     }
9234     return offset;
9235 }
9236
9237 static guint
9238 fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9239 {
9240     offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
9241                                           "vtClass: ", BACnetVTClass);
9242     return fApplicationTypes(tvb, pinfo, tree, offset, "local VT Session ID: ");
9243 }
9244
9245 static guint
9246 fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9247 {
9248     return fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
9249 }
9250
9251 static guint
9252 fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9253 {
9254     guint lastoffset = 0;
9255
9256     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9257         lastoffset = offset;
9258         offset= fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
9259         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9260     }
9261     return offset;
9262 }
9263
9264 static guint
9265 fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9266 {
9267     offset= fApplicationTypes(tvb, pinfo, tree, offset, "VT Session ID: ");
9268     offset = fApplicationTypes(tvb, pinfo, tree, offset, "VT New Data: ");
9269     return fApplicationTypes(tvb, pinfo, tree, offset, "VT Data Flag: ");
9270 }
9271
9272 static guint
9273 fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9274 {
9275     guint lastoffset = 0;
9276
9277     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9278         lastoffset = offset;
9279
9280         switch (fTagNo(tvb, offset)) {
9281         case 0: /* BOOLEAN */
9282             offset = fBooleanTag(tvb, pinfo, tree, offset, "all New Data Accepted: ");
9283             break;
9284         case 1: /* Unsigned OPTIONAL */
9285             offset = fUnsignedTag(tvb, pinfo, tree, offset, "accepted Octet Count: ");
9286             break;
9287         default:
9288             return offset;
9289         }
9290         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9291     }
9292     return offset;
9293 }
9294
9295 static guint
9296 fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9297 {
9298     guint lastoffset = 0;
9299
9300     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9301         lastoffset = offset;
9302
9303         switch (fTagNo(tvb, offset)) {
9304         case 0: /* Unsigned32 */
9305             offset = fUnsignedTag(tvb, pinfo, tree, offset, "pseudo Random Number: ");
9306             break;
9307         case 1: /* expected Invoke ID Unsigned8 OPTIONAL */
9308             proto_tree_add_item(tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
9309             break;
9310         case 2: /* Chararacter String OPTIONAL */
9311             offset = fCharacterString(tvb, pinfo, tree, offset, "operator Name: ");
9312             break;
9313         case 3: /* Chararacter String OPTIONAL */
9314             offset = fCharacterString(tvb, pinfo, tree, offset, "operator Password: ");
9315             break;
9316         case 4: /* Boolean OPTIONAL */
9317             offset = fBooleanTag(tvb, pinfo, tree, offset, "start Encyphered Session: ");
9318             break;
9319         default:
9320             return offset;
9321         }
9322         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9323     }
9324     return offset;
9325 }
9326
9327 static guint
9328 fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9329 {
9330     return fApplicationTypes(tvb, pinfo, tree, offset, "modified Random Number: ");
9331 }
9332
9333 static guint
9334 fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9335 {
9336     offset = fObjectIdentifier(tvb, pinfo, tree, offset); /* Requesting Device Identifier */
9337     offset = fAddress(tvb, pinfo, tree, offset);
9338     offset = fObjectIdentifier(tvb, pinfo, tree, offset); /* Remote Device Identifier */
9339     return fAddress(tvb, pinfo, tree, offset);
9340 }
9341
9342 static guint
9343 fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9344 {
9345     /* Same as AddListElement request after service choice */
9346     return fAddListElementRequest(tvb, pinfo, tree, offset);
9347 }
9348
9349 static guint
9350 fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9351 {
9352     return fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
9353 }
9354
9355 static guint
9356 fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9357 {
9358     guint       lastoffset = 0, len;
9359     guint8      tag_no, tag_info;
9360     guint32     lvt;
9361     proto_tree *subtree = tree;
9362
9363     /* set the optional global properties to indicate not-used */
9364     propertyArrayIndex = -1;
9365     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9366         lastoffset = offset;
9367         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9368         if (tag_is_closing(tag_info)) {
9369             offset += len;
9370             subtree = tree;
9371             continue;
9372         }
9373         switch (tag_no) {
9374         case 0: /* objectIdentifier */
9375             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9376             break;
9377         case 1: /* propertyIdentifier */
9378             offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
9379             break;
9380         case 2: /* propertyArrayIndex */
9381             offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
9382             break;
9383         case 3: /* propertyValue */
9384             offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
9385             break;
9386         default:
9387             break;
9388         }
9389         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9390     }
9391     return offset;
9392 }
9393
9394 static guint
9395 fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9396 {
9397     guint       lastoffset = 0;
9398     guint8      tag_no, tag_info;
9399     guint32     lvt;
9400     proto_tree *subtree = tree;
9401
9402     /* set the optional global properties to indicate not-used */
9403     propertyArrayIndex = -1;
9404     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9405         lastoffset = offset;
9406         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9407         /* quit loop if we spot a closing tag */
9408         if (tag_is_closing(tag_info)) {
9409             break;
9410         }
9411
9412         switch (tag_no) {
9413         case 0: /* objectIdentifier */
9414             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9415             break;
9416         case 1: /* propertyIdentifier */
9417             offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
9418             break;
9419         case 2: /* propertyArrayIndex */
9420             offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
9421             break;
9422         case 3: /* propertyValue */
9423             offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
9424             break;
9425         case 4: /* Priority (only used for write) */
9426             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
9427             break;
9428         default:
9429             return offset;
9430         }
9431         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9432     }
9433     return offset;
9434 }
9435
9436 static guint
9437 fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9438 {
9439     guint   lastoffset = 0, len;
9440     guint8  tag_no, tag_info;
9441     guint32 lvt;
9442
9443     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9444         lastoffset = offset;
9445         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9446         /* maybe a listOfwriteAccessSpecifications if we spot a closing tag */
9447         if (tag_is_closing(tag_info)) {
9448             offset += len;
9449             continue;
9450         }
9451
9452         switch (tag_no) {
9453         case 0: /* objectIdentifier */
9454             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9455             break;
9456         case 1: /* listOfPropertyValues */
9457             if (tag_is_opening(tag_info)) {
9458                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9459                 offset  = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
9460                 break;
9461             }
9462             FAULT;
9463             break;
9464         default:
9465             return offset;
9466         }
9467         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9468     }
9469     return offset;
9470 }
9471
9472 static guint
9473 fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9474 {
9475     if (offset >= tvb_reported_length(tvb))
9476         return offset;
9477
9478     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9479     return fWriteAccessSpecification(tvb, pinfo, tree, offset);
9480 }
9481
9482 static guint
9483 fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list)
9484 {
9485     guint   lastoffset = 0;
9486     guint8  tag_no, tag_info;
9487     guint32 lvt;
9488
9489     /* set the optional global properties to indicate not-used */
9490     propertyArrayIndex = -1;
9491     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9492         lastoffset = offset;
9493         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9494         if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
9495             return offset;
9496         } else if (tag_is_opening(tag_info)) { /* opening Tag, but not for me */
9497             return offset;
9498         }
9499         switch (tag_no-tagoffset) {
9500         case 0: /* PropertyIdentifier */
9501             offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
9502             break;
9503         case 1: /* propertyArrayIndex */
9504             offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
9505             if (list != 0) break; /* Continue decoding if this may be a list */
9506         default:
9507             lastoffset = offset; /* Set loop end condition */
9508             break;
9509         }
9510         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9511     }
9512     return offset;
9513 }
9514
9515 static guint
9516 fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list)
9517 {
9518     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9519     return fPropertyReference(tvb, pinfo, tree, offset, 0, list);
9520 }
9521
9522 static guint
9523 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9524 {
9525     guint lastoffset = 0;
9526
9527     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9528         lastoffset = offset;
9529
9530         switch (fTagNo(tvb, offset)) {
9531         case 0: /* ObjectIdentifier */
9532             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9533             break;
9534         case 1: /* PropertyIdentifier and propertyArrayIndex */
9535             offset = fPropertyReference(tvb, pinfo, tree, offset, 1, 0);
9536             col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9537         default:
9538             lastoffset = offset; /* Set loop end condition */
9539             break;
9540         }
9541         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9542     }
9543     return offset;
9544 }
9545
9546 #if 0
9547 static guint
9548 fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, guint offset)
9549 {
9550     guint       lastoffset = 0;
9551     guint8      tag_no, tag_info;
9552     guint32     lvt;
9553     proto_tree* subtree = tree;
9554     proto_item* tt;
9555
9556     while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
9557         lastoffset = offset;
9558         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9559         if (tag_is_closing(tag_info)) {
9560             offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
9561                 &tag_no, &tag_info, &lvt);
9562             continue;
9563         }
9564         switch (tag_no) {
9565         case 0: /* ObjectIdentifier */
9566             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9567             break;
9568         case 1: /* PropertyIdentifier */
9569             offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
9570             break;
9571         case 2: /* propertyArrayIndex */
9572             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "property Array Index: ");
9573             break;
9574         case 3:  /* Value */
9575             offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
9576             break;
9577         case 4:  /* Priority */
9578             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
9579             break;
9580         default:
9581             break;
9582         }
9583     }
9584     return offset;
9585 }
9586 #endif
9587
9588 static guint
9589 fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9590 {
9591     char  i = 1, ar[256];
9592     guint lastoffset = 0;
9593
9594     if (propertyArrayIndex > 0) {
9595         /* BACnetARRAY index 0 refers to the length
9596         of the array, not the elements of the array.
9597         BACnetARRAY index -1 is our internal flag that
9598         the optional index was not used.
9599         BACnetARRAY refers to this as all elements of the array.
9600         If the optional index is specified for a BACnetARRAY,
9601         then that specific array element is referenced. */
9602         i = propertyArrayIndex;
9603     }
9604     while (tvb_reported_length_remaining(tvb, offset) > 0) {
9605         /* exit loop if nothing happens inside */
9606         lastoffset = offset;
9607         g_snprintf(ar, sizeof(ar), "%s[%d]: ",
9608             val_to_split_str(87 , 512,
9609                 BACnetPropertyIdentifier,
9610                 ASHRAE_Reserved_Fmt,
9611                 Vendor_Proprietary_Fmt),
9612             i++);
9613         /* DMR Should be fAbstractNSyntax, but that's where we came from! */
9614         offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9615         /* there are only 16 priority array elements */
9616         if (i > 16) {
9617             break;
9618         }
9619         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9620     }
9621
9622     return offset;
9623 }
9624
9625 static guint
9626 fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9627 {
9628     guint lastoffset = 0;
9629
9630     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9631         lastoffset = offset;
9632
9633         switch (fTagNo(tvb, offset)) {
9634         case 0: /* deviceIdentifier - OPTIONAL */
9635             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9636             break;
9637         case 1: /* ObjectIdentifier */
9638             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9639             break;
9640         default:
9641             return offset;
9642         }
9643         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9644     }
9645     return offset;
9646 }
9647
9648 static guint
9649 fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9650 {
9651     guint8 tag_no, tag_info;
9652     guint32 lvt;
9653     guint lastoffset = 0;
9654
9655     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9656         lastoffset = offset;
9657         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9658         /* quit loop if we spot an un-matched closing tag */
9659         if (tag_is_closing(tag_info)) {
9660             break;
9661         }
9662         switch (tag_no) {
9663         case 0: /* calendarEntry */
9664             if (tag_is_opening(tag_info)) {
9665                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9666                 offset  = fCalendarEntry(tvb, pinfo, subtree, offset);
9667                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9668             }
9669             break;
9670         case 1: /* calendarReference */
9671             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9672             break;
9673         case 2: /* list of BACnetTimeValue */
9674             if (tag_is_opening(tag_info)) {
9675                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9676                 offset  = fTimeValue(tvb, pinfo, subtree, offset);
9677                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9678                 break;
9679             }
9680             FAULT;
9681             break;
9682         case 3: /* eventPriority */
9683             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "event priority: ");
9684             break;
9685         default:
9686             return offset;
9687         }
9688         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9689     }
9690     return offset;
9691 }
9692
9693 static guint
9694 fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9695 {
9696     guint   lastoffset = 0, len;
9697     guint8  tag_no, tag_info;
9698     guint32 lvt;
9699
9700     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9701         lastoffset = offset;
9702         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9703         /* maybe a listOfSelectionCriteria if we spot a closing tag */
9704         if (tag_is_closing(tag_info)) {
9705             offset += len;
9706             continue;
9707         }
9708
9709         switch (fTagNo(tvb, offset)) {
9710         case 0: /* propertyIdentifier */
9711             offset  = fPropertyIdentifier(tvb, pinfo, tree, offset);
9712             break;
9713         case 1: /* propertyArrayIndex */
9714             offset  = fPropertyArrayIndex(tvb, pinfo, tree, offset);
9715             break;
9716         case 2: /* relationSpecifier */
9717             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
9718                 "relation Specifier: ", BACnetRelationSpecifier);
9719             break;
9720         case 3: /* comparisonValue */
9721             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9722             offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
9723             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9724             break;
9725         default:
9726             return offset;
9727         }
9728         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9729     }
9730     return offset;
9731 }
9732
9733 static guint
9734 fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9735 {
9736     guint   lastoffset = 0;
9737     guint8  tag_no, tag_info;
9738     guint32 lvt;
9739
9740     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9741         lastoffset = offset;
9742         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9743         /* quit loop if we spot a closing tag */
9744         if (tag_is_closing(tag_info)) {
9745             break;
9746         }
9747
9748         switch (tag_no) {
9749         case 0: /* selectionLogic */
9750             offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
9751                 "selection Logic: ", BACnetSelectionLogic);
9752             break;
9753         case 1: /* listOfSelectionCriteria */
9754             if (tag_is_opening(tag_info)) {
9755                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9756                 offset  = fSelectionCriteria(tvb, pinfo, subtree, offset);
9757                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9758                 break;
9759             }
9760             FAULT;
9761             break;
9762         default:
9763             return offset;
9764         }
9765         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9766     }
9767     return offset;
9768 }
9769
9770
9771 static guint
9772 fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *subtree, guint offset)
9773 {
9774     guint   lastoffset = 0;
9775     guint8  tag_no, tag_info;
9776     guint32 lvt;
9777
9778     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9779         lastoffset = offset;
9780         fTagHeader (tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9781
9782         if (tag_is_opening(tag_info) && tag_no < 2) {
9783             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9784             switch (tag_no) {
9785             case 0: /* objectSelectionCriteria */
9786                 offset = fObjectSelectionCriteria(tvb, pinfo, subtree, offset);
9787                 break;
9788             case 1: /* listOfPropertyReferences */
9789                 offset = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
9790                 break;
9791             default:
9792                 return offset;
9793             }
9794             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9795         }
9796         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9797     }
9798     return offset;
9799 }
9800
9801 static guint
9802 fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9803 {
9804     guint       lastoffset = 0;
9805     guint8      tag_no, tag_info;
9806     guint32     lvt;
9807     proto_tree *subtree = tree;
9808
9809     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9810         lastoffset = offset;
9811         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9812         switch (tag_no) {
9813         case 0: /* objectIdentifier */
9814             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9815             break;
9816         case 1: /* listOfPropertyReferences */
9817             if (tag_is_opening(tag_info)) {
9818                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfPropertyReferences");
9819                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9820                 offset  = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
9821             } else if (tag_is_closing(tag_info)) {
9822                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
9823                     &tag_no, &tag_info, &lvt);
9824                 subtree = tree;
9825             } else {
9826                 /* error condition: let caller handle */
9827                 return offset;
9828             }
9829             break;
9830         default:
9831             return offset;
9832         }
9833         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9834     }
9835     return offset;
9836 }
9837
9838 static guint
9839 fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9840 {
9841     guint       lastoffset = 0, len;
9842     guint8      tag_no;
9843     guint8      tag_info;
9844     guint32     lvt;
9845     proto_tree *subtree = tree;
9846
9847     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9848         lastoffset = offset;
9849         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9850         /* maybe a listOfReadAccessResults if we spot a closing tag here */
9851         if (tag_is_closing(tag_info)) {
9852             offset += len;
9853             if ((tag_no == 4 || tag_no == 5) && (subtree != tree)) subtree = subtree->parent; /* Value and error have extra subtree */
9854             continue;
9855         }
9856
9857         switch (tag_no) {
9858         case 0: /* objectSpecifier */
9859             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9860             break;
9861         case 1: /* list of Results */
9862             if (tag_is_opening(tag_info)) {
9863                 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfResults");
9864                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9865                 break;
9866             }
9867             FAULT;
9868             break;
9869         case 2: /* propertyIdentifier */
9870             offset = fPropertyIdentifierValue(tvb, pinfo, subtree, offset, 2);
9871             break;
9872         case 5: /* propertyAccessError */
9873             if (tag_is_opening(tag_info)) {
9874                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "propertyAccessError");
9875                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9876                 /* Error Code follows */
9877                 offset  = fError(tvb, pinfo, subtree, offset);
9878                 break;
9879             }
9880             FAULT;
9881             break;
9882         default:
9883             return offset;
9884         }
9885         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9886     }
9887     return offset;
9888 }
9889
9890
9891 static guint
9892 fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9893 {
9894     /* listOfReadAccessResults */
9895     return fReadAccessResult(tvb, pinfo, tree, offset);
9896 }
9897
9898
9899 static guint
9900 fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9901 {
9902     guint   lastoffset = 0;
9903     guint8  tag_no, tag_info;
9904     guint32 lvt;
9905
9906     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9907         lastoffset = offset;
9908         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9909
9910         if (tag_no < 2) {
9911             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9912             switch (tag_no) {
9913             case 0: /* objectSpecifier */
9914                 switch (fTagNo(tvb, offset)) { /* choice of objectType or objectIdentifier */
9915                 case 0: /* objectType */
9916                     offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset, "Object Type: ", BACnetObjectType, 128);
9917                     break;
9918                 case 1: /* objectIdentifier */
9919                     offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9920                     break;
9921                 default:
9922                     break;
9923                 }
9924                 break;
9925             case 1: /* propertyValue */
9926                 if (tag_is_opening(tag_info)) {
9927                     offset = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
9928                     break;
9929                 }
9930                 FAULT;
9931                 break;
9932             default:
9933                 break;
9934             }
9935             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9936         }
9937         if (offset == lastoffset) break;    /* nothing happened, exit loop */
9938     }
9939     return offset;
9940 }
9941
9942 static guint
9943 fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9944 {
9945     return fObjectIdentifier(tvb, pinfo, tree, offset);
9946 }
9947
9948 static guint
9949 fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9950 {
9951     guint8      tag_no, tag_info;
9952     guint32     lvt;
9953     proto_tree *subtree = tree;
9954
9955     offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
9956
9957     if (tvb_reported_length_remaining(tvb, offset) > 0) {
9958         /* optional range choice */
9959         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9960         if (tag_is_opening(tag_info)) {
9961             subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL,
9962                 val_to_str_const(tag_no, BACnetReadRangeOptions, "unknown range option"));
9963             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9964             switch (tag_no) {
9965             case 3: /* range byPosition */
9966             case 6: /* range bySequenceNumber, 2004 spec */
9967                 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Index: ");
9968                 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
9969                 break;
9970             case 4: /* range byTime - deprecated in 2004 */
9971             case 7: /* 2004 spec */
9972                 offset = fDateTime(tvb, pinfo, subtree, offset, "reference Date/Time: ");
9973                 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
9974                 break;
9975             case 5: /* range timeRange - deprecated in 2004 */
9976                 offset = fDateTime(tvb, pinfo, subtree, offset, "beginning Time: ");
9977                 offset = fDateTime(tvb, pinfo, subtree, offset, "ending Time: ");
9978                 break;
9979             default:
9980                 break;
9981             }
9982             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9983         }
9984     }
9985     return offset;
9986 }
9987
9988 static guint
9989 fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9990 {
9991     guint8      tag_no, tag_info;
9992     guint32     lvt;
9993     proto_tree *subtree = tree;
9994
9995     /* set the optional global properties to indicate not-used */
9996     propertyArrayIndex = -1;
9997     /* objectIdentifier, propertyIdentifier, and
9998        OPTIONAL propertyArrayIndex */
9999     offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
10000     /* resultFlags => BACnetResultFlags ::= BIT STRING */
10001     offset = fBitStringTagVS(tvb, pinfo, tree, offset,
10002         "resultFlags: ",
10003         BACnetResultFlags);
10004     /* itemCount */
10005     offset = fUnsignedTag(tvb, pinfo, subtree, offset, "item Count: ");
10006     /* itemData */
10007     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10008     if (tag_is_opening(tag_info)) {
10009         col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10010         subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "itemData");
10011         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10012         offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10013         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10014     }
10015     /* firstSequenceNumber - OPTIONAL */
10016     if (tvb_reported_length_remaining(tvb, offset) > 0) {
10017         offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "first Sequence Number: ");
10018     }
10019
10020     return offset;
10021 }
10022
10023 static guint
10024 fAccessMethod(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10025 {
10026     guint       lastoffset = 0;
10027     guint32     lvt;
10028     guint8      tag_no, tag_info;
10029     proto_tree* subtree = NULL;
10030
10031     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10032
10033     if (tag_is_opening(tag_info)) {
10034         subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL,
10035             val_to_str_const(tag_no, BACnetFileAccessOption, "invalid access method"));
10036         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10037         offset  = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "invalid option"));
10038         offset  = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileWriteInfo, "unknown option"));
10039
10040         if (tag_no == 1) {
10041             while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
10042                 /* exit loop if nothing happens inside */
10043                 lastoffset = offset;
10044                 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "Record Data: ");
10045             }
10046         }
10047
10048         if ((bacapp_flags & BACAPP_MORE_SEGMENTS) == 0) {
10049             /* More Flag is not set, so we can look for closing tag in this segment */
10050             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10051             if (tag_is_closing(tag_info)) {
10052                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10053             }
10054         }
10055     }
10056     return offset;
10057 }
10058
10059 static guint
10060 fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10061 {
10062     guint8      tag_no, tag_info;
10063     guint32     lvt;
10064     proto_tree *subtree = tree;
10065
10066     offset = fObjectIdentifier(tvb, pinfo, tree, offset);
10067
10068     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10069
10070     if (tag_is_opening(tag_info)) {
10071         subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL,
10072                         val_to_str_const(tag_no, BACnetFileAccessOption, "unknown access method"));
10073         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10074         offset  = fSignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
10075         offset  = fUnsignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileRequestCount, "unknown option"));
10076         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10077     }
10078     return offset;
10079 }
10080
10081 static guint
10082 fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10083 {
10084
10085     offset = fObjectIdentifier(tvb, pinfo, tree, offset); /* file Identifier */
10086     offset = fAccessMethod(tvb, pinfo, tree, offset);
10087
10088     return offset;
10089 }
10090
10091 static guint
10092 fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10093 {
10094     guint tag_no = fTagNo(tvb, offset);
10095     return fSignedTag(tvb, pinfo, tree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
10096 }
10097
10098 static guint
10099 fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10100 {
10101     offset = fApplicationTypes(tvb, pinfo, tree, offset, "End Of File: ");
10102     offset = fAccessMethod(tvb, pinfo, tree, offset);
10103
10104     return offset;
10105 }
10106
10107 static guint
10108 fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
10109 {
10110     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10111     return fReadAccessSpecification(tvb, pinfo, subtree, offset);
10112 }
10113
10114 static guint
10115 fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10116 {
10117     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10118     return fReadAccessResult(tvb, pinfo, tree, offset);
10119 }
10120
10121 static guint
10122 fConfirmedServiceRequest(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: /* acknowledgeAlarm */
10129         offset = fAcknowledgeAlarmRequest(tvb, pinfo, tree, offset);
10130         break;
10131     case 1: /* confirmedCOVNotification */
10132         offset = fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
10133         break;
10134     case 2: /* confirmedEventNotification */
10135         offset = fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
10136         break;
10137     case 3: /* confirmedGetAlarmSummary conveys no parameters */
10138         break;
10139     case 4: /* getEnrollmentSummaryRequest */
10140         offset = fGetEnrollmentSummaryRequest(tvb, pinfo, tree, offset);
10141         break;
10142     case 5: /* subscribeCOVRequest */
10143         offset = fSubscribeCOVRequest(tvb, pinfo, tree, offset);
10144         break;
10145     case 6: /* atomicReadFile-Request */
10146         offset = fAtomicReadFileRequest(tvb, pinfo, tree, offset);
10147         break;
10148     case 7: /* atomicWriteFile-Request */
10149         offset = fAtomicWriteFileRequest(tvb, pinfo, tree, offset);
10150         break;
10151     case 8: /* AddListElement-Request */
10152         offset = fAddListElementRequest(tvb, pinfo, tree, offset);
10153         break;
10154     case 9: /* removeListElement-Request */
10155         offset = fRemoveListElementRequest(tvb, pinfo, tree, offset);
10156         break;
10157     case 10: /* createObjectRequest */
10158         offset = fCreateObjectRequest(tvb, pinfo, tree, offset);
10159         break;
10160     case 11: /* deleteObject */
10161         offset = fDeleteObjectRequest(tvb, pinfo, tree, offset);
10162         break;
10163     case 12:
10164         offset = fReadPropertyRequest(tvb, pinfo, tree, offset);
10165         break;
10166     case 13:
10167         offset = fReadPropertyConditionalRequest(tvb, pinfo, tree, offset);
10168         break;
10169     case 14:
10170         offset = fReadPropertyMultipleRequest(tvb, pinfo, tree, offset);
10171         break;
10172     case 15:
10173         offset = fWritePropertyRequest(tvb, pinfo, tree, offset);
10174         break;
10175     case 16:
10176         offset = fWritePropertyMultipleRequest(tvb, pinfo, tree, offset);
10177         break;
10178     case 17:
10179         offset = fDeviceCommunicationControlRequest(tvb, pinfo, tree, offset);
10180         break;
10181     case 18:
10182         offset = fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
10183         break;
10184     case 19:
10185         offset = fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
10186         break;
10187     case 20:
10188         offset = fReinitializeDeviceRequest(tvb, pinfo, tree, offset);
10189         break;
10190     case 21:
10191         offset = fVtOpenRequest(tvb, pinfo, tree, offset);
10192         break;
10193     case 22:
10194         offset = fVtCloseRequest(tvb, pinfo, tree, offset);
10195         break;
10196     case 23:
10197         offset = fVtDataRequest(tvb, pinfo, tree, offset);
10198         break;
10199     case 24:
10200         offset = fAuthenticateRequest(tvb, pinfo, tree, offset);
10201         break;
10202     case 25:
10203         offset = fRequestKeyRequest(tvb, pinfo, tree, offset);
10204         break;
10205     case 26:
10206         offset = fReadRangeRequest(tvb, pinfo, tree, offset);
10207         break;
10208     case 27:
10209         offset = fLifeSafetyOperationRequest(tvb, pinfo, tree, offset, NULL);
10210         break;
10211     case 28:
10212         offset = fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
10213         break;
10214     case 29:
10215         offset = fGetEventInformationRequest(tvb, pinfo, tree, offset);
10216         break;
10217     default:
10218         return offset;
10219     }
10220     return offset;
10221 }
10222
10223 static guint
10224 fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
10225 {
10226     if (tvb_reported_length_remaining(tvb, offset) <= 0)
10227         return offset;
10228
10229     switch (service_choice) {
10230     case 3: /* confirmedEventNotificationAck */
10231         offset = fGetAlarmSummaryAck(tvb, pinfo, tree, offset);
10232         break;
10233     case 4: /* getEnrollmentSummaryAck */
10234         offset = fGetEnrollmentSummaryAck(tvb, pinfo, tree, offset);
10235         break;
10236     case 6: /* atomicReadFile */
10237         offset = fAtomicReadFileAck(tvb, pinfo, tree, offset);
10238         break;
10239     case 7: /* atomicReadFileAck */
10240         offset = fAtomicWriteFileAck(tvb, pinfo, tree, offset);
10241         break;
10242     case 10: /* createObject */
10243         offset = fCreateObjectAck(tvb, pinfo, tree, offset);
10244         break;
10245     case 12:
10246         offset = fReadPropertyAck(tvb, pinfo, tree, offset);
10247         break;
10248     case 13:
10249         offset = fReadPropertyConditionalAck(tvb, pinfo, tree, offset);
10250         break;
10251     case 14:
10252         offset = fReadPropertyMultipleAck(tvb, pinfo, tree, offset);
10253         break;
10254     case 18:
10255         offset = fConfirmedPrivateTransferAck(tvb, pinfo, tree, offset);
10256         break;
10257     case 21:
10258         offset = fVtOpenAck(tvb, pinfo, tree, offset);
10259         break;
10260     case 23:
10261         offset = fVtDataAck(tvb, pinfo, tree, offset);
10262         break;
10263     case 24:
10264         offset = fAuthenticateAck(tvb, pinfo, tree, offset);
10265         break;
10266     case 26:
10267         offset = fReadRangeAck(tvb, pinfo, tree, offset);
10268         break;
10269     case 29:
10270         offset = fGetEventInformationACK(tvb, pinfo, tree, offset);
10271         break;
10272     default:
10273         return offset;
10274     }
10275     return offset;
10276 }
10277
10278 static guint
10279 fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10280 {
10281     /* BACnetObjectIdentifier */
10282     offset = fApplicationTypes(tvb, pinfo, tree, offset, "BACnet Object Identifier: ");
10283
10284     /* MaxAPDULengthAccepted */
10285     offset = fApplicationTypes(tvb, pinfo, tree, offset, "Maximum ADPU Length Accepted: ");
10286
10287     /* segmentationSupported */
10288     offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
10289         "Segmentation Supported: ", BACnetSegmentation);
10290
10291     /* vendor ID */
10292     return fVendorIdentifier(tvb, pinfo, tree, offset);
10293 }
10294
10295 static guint
10296 fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10297 {
10298     /* BACnetDeviceIdentifier */
10299     offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device Identifier: ");
10300
10301     /* BACnetObjectIdentifier */
10302     offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
10303
10304     /* ObjectName */
10305     return fApplicationTypes(tvb, pinfo, tree, offset, "Object Name: ");
10306
10307 }
10308
10309 static guint
10310 fWhoIsRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, guint offset)
10311 {
10312     guint   lastoffset = 0;
10313     guint   val;
10314     guint8  tag_len;
10315
10316     guint8  tag_no, tag_info;
10317     guint32 lvt;
10318
10319     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10320         lastoffset = offset;
10321
10322         tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10323
10324         switch (tag_no) {
10325         case 0:
10326             /* DeviceInstanceRangeLowLimit Optional */
10327             if (col_get_writable(pinfo->cinfo) && fUnsigned32(tvb, offset+tag_len, lvt, &val))
10328                 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
10329             offset = fDevice_Instance(tvb, pinfo, tree, offset,
10330                 hf_Device_Instance_Range_Low_Limit);
10331             break;
10332         case 1:
10333             /* DeviceInstanceRangeHighLimit Optional but
10334                 required if DeviceInstanceRangeLowLimit is there */
10335             if (col_get_writable(pinfo->cinfo) && fUnsigned32(tvb, offset+tag_len, lvt, &val))
10336                 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
10337             offset = fDevice_Instance(tvb, pinfo, tree, offset,
10338                 hf_Device_Instance_Range_High_Limit);
10339             break;
10340         default:
10341             return offset;
10342         }
10343         if (offset == lastoffset) break;     /* nothing happened, exit loop */
10344     }
10345     return offset;
10346 }
10347
10348 static guint
10349 fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
10350 {
10351     if (tvb_reported_length_remaining(tvb, offset) <= 0)
10352         return offset;
10353
10354     switch (service_choice) {
10355     case 0: /* I-Am-Request */
10356         offset = fIAmRequest(tvb, pinfo, tree, offset);
10357         break;
10358     case 1: /* i-Have Request */
10359         offset = fIHaveRequest(tvb, pinfo, tree, offset);
10360     break;
10361     case 2: /* unconfirmedCOVNotification */
10362         offset = fUnconfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
10363         break;
10364     case 3: /* unconfirmedEventNotification */
10365         offset = fUnconfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
10366         break;
10367     case 4: /* unconfirmedPrivateTransfer */
10368         offset = fUnconfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
10369         break;
10370     case 5: /* unconfirmedTextMessage */
10371         offset = fUnconfirmedTextMessageRequest(tvb, pinfo, tree, offset);
10372         break;
10373     case 206: /* utc-time-synchronization-recipients */
10374     case 6: /* timeSynchronization */
10375         offset = fTimeSynchronizationRequest(tvb, pinfo, tree, offset);
10376         break;
10377     case 7: /* who-Has */
10378         offset = fWhoHas(tvb, pinfo, tree, offset);
10379         break;
10380     case 8: /* who-Is */
10381         offset = fWhoIsRequest(tvb, pinfo, tree, offset);
10382         break;
10383     case 9: /* utcTimeSynchronization */
10384         offset = fUTCTimeSynchronizationRequest(tvb, pinfo, tree, offset);
10385         break;
10386     default:
10387         break;
10388     }
10389     return offset;
10390 }
10391
10392 static guint
10393 fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset, guint8 ack,
10394         gint *svc, proto_item **tt)
10395 {
10396     proto_item *tc;
10397     proto_tree *bacapp_tree_control;
10398     gint        tmp;
10399     guint       extra = 2;
10400
10401     bacapp_seq = 0;
10402     tmp = (gint) tvb_get_guint8(tvb, offset);
10403     bacapp_flags = tmp & 0x0f;
10404
10405     if (ack == 0) {
10406         extra = 3;
10407     }
10408     *svc = (gint) tvb_get_guint8(tvb, offset+extra);
10409     if (bacapp_flags & 0x08)
10410         *svc = (gint) tvb_get_guint8(tvb, offset+extra+2);
10411
10412     proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
10413     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_pduflags, tvb, offset, 1, ENC_BIG_ENDIAN);
10414     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp_control);
10415
10416     proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, ENC_BIG_ENDIAN);
10417     proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, ENC_BIG_ENDIAN);
10418     if (ack == 0) { /* The following are for ConfirmedRequest, not Complex ack */
10419         proto_tree_add_item(bacapp_tree_control, hf_bacapp_SA, tvb, offset++, 1, ENC_BIG_ENDIAN);
10420         proto_tree_add_item(bacapp_tree, hf_bacapp_response_segments, tvb,
10421                             offset, 1, ENC_BIG_ENDIAN);
10422         proto_tree_add_item(bacapp_tree, hf_bacapp_max_adpu_size, tvb,
10423                             offset, 1, ENC_BIG_ENDIAN);
10424     }
10425     offset++;
10426     proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
10427     if (bacapp_flags & 0x08) {
10428         bacapp_seq = tvb_get_guint8(tvb, offset);
10429         proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
10430             offset++, 1, ENC_BIG_ENDIAN);
10431         proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
10432             offset++, 1, ENC_BIG_ENDIAN);
10433     }
10434     *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
10435                   offset++, 1, ENC_BIG_ENDIAN);
10436     return offset;
10437 }
10438
10439 static guint
10440 fContinueConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
10441 {   /* BACnet-Confirmed-Request */
10442     /* ASHRAE 135-2001 20.1.2 */
10443
10444     return fConfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, svc);
10445 }
10446
10447 static guint
10448 fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10449 {   /* BACnet-Confirmed-Request */
10450     /* ASHRAE 135-2001 20.1.2 */
10451     gint        svc;
10452     proto_item *tt = 0;
10453
10454     offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 0, &svc, &tt);
10455     return fContinueConfirmedRequestPDU(tvb, pinfo, bacapp_tree, offset, svc);
10456 }
10457
10458 static guint
10459 fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10460 {   /* BACnet-Unconfirmed-Request-PDU */
10461     /* ASHRAE 135-2001 20.1.3 */
10462
10463     gint tmp;
10464
10465     proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10466
10467     tmp = tvb_get_guint8(tvb, offset);
10468     proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
10469         offset++, 1, ENC_BIG_ENDIAN);
10470     /* Service Request follows... Variable Encoding 20.2ff */
10471     return fUnconfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, tmp);
10472 }
10473
10474 static guint
10475 fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10476 {   /* BACnet-Simple-Ack-PDU */
10477     /* ASHRAE 135-2001 20.1.4 */
10478
10479     proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10480
10481     proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
10482                 offset++, 1, ENC_BIG_ENDIAN);
10483     proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
10484                 offset++, 1, ENC_BIG_ENDIAN);
10485
10486     return offset;
10487 }
10488
10489 static guint
10490 fContinueComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
10491 {   /* BACnet-Complex-Ack-PDU */
10492     /* ASHRAE 135-2001 20.1.5 */
10493
10494     /* Service ACK follows... */
10495     return fConfirmedServiceAck(tvb, pinfo, bacapp_tree, offset, svc);
10496 }
10497
10498 static guint
10499 fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10500 {   /* BACnet-Complex-Ack-PDU */
10501     /* ASHRAE 135-2001 20.1.5 */
10502     gint        svc;
10503     proto_item *tt = 0;
10504
10505     offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 1, &svc, &tt);
10506     return fContinueComplexAckPDU(tvb, pinfo, bacapp_tree, offset, svc);
10507 }
10508
10509 static guint
10510 fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10511 {   /* BACnet-SegmentAck-PDU */
10512     /* ASHRAE 135-2001 20.1.6 */
10513
10514     proto_item *tc;
10515     proto_tree *bacapp_tree_control;
10516
10517     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
10518     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10519
10520     proto_tree_add_item(bacapp_tree_control, hf_bacapp_NAK, tvb, offset, 1, ENC_BIG_ENDIAN);
10521     proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
10522     proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10523                 offset++, 1, ENC_BIG_ENDIAN);
10524     proto_tree_add_item(bacapp_tree_control, hf_bacapp_sequence_number, tvb,
10525                 offset++, 1, ENC_BIG_ENDIAN);
10526     proto_tree_add_item(bacapp_tree_control, hf_bacapp_window_size, tvb,
10527                 offset++, 1, ENC_BIG_ENDIAN);
10528     return offset;
10529 }
10530
10531 static guint
10532 fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10533 {
10534     guint8  tag_info   = 0;
10535     guint8  parsed_tag = 0;
10536     guint32 lvt        = 0;
10537
10538     offset += fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
10539     offset  = fError(tvb, pinfo, tree, offset);
10540     return offset + fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
10541 }
10542
10543 static guint
10544 fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10545 {
10546     guint       lastoffset        = 0;
10547     guint8      tag_no            = 0, tag_info = 0;
10548     guint32     lvt               = 0;
10549     proto_tree *subtree           = tree;
10550
10551     guint       vendor_identifier = 0;
10552     guint       service_number    = 0;
10553     guint8      tag_len           = 0;
10554
10555     while (tvb_reported_length_remaining(tvb, offset) > 0) {
10556         /* exit loop if nothing happens inside */
10557         lastoffset = offset;
10558         tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10559         switch (tag_no) {
10560         case 0: /* errorType */
10561             offset = fContextTaggedError(tvb, pinfo, subtree, offset);
10562             break;
10563         case 1: /* vendorID */
10564             fUnsigned32(tvb, offset+tag_len, lvt, &vendor_identifier);
10565             if (col_get_writable(pinfo->cinfo))
10566                 col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ",    vendor_identifier);
10567             offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
10568             break;
10569         case 2: /* serviceNumber */
10570             fUnsigned32(tvb, offset+tag_len, lvt, &service_number);
10571             if (col_get_writable(pinfo->cinfo))
10572                 col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ",   service_number);
10573             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
10574             break;
10575         case 3: /* errorParameters */
10576             if (tag_is_opening(tag_info)) {
10577                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1,
10578                     ett_bacapp_value, NULL, "error Parameters");
10579                 propertyIdentifier = -1;
10580                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10581                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10582             } else if (tag_is_closing(tag_info)) {
10583                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
10584                     &tag_no, &tag_info, &lvt);
10585                 subtree = tree;
10586             } else {
10587                 /* error condition: let caller handle */
10588                 return offset;
10589             }
10590             break;
10591         default:
10592             return offset;
10593         }
10594         if (offset == lastoffset) break;     /* nothing happened, exit loop */
10595     }
10596     return offset;
10597 }
10598
10599 static guint
10600 fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10601 {
10602     guint lastoffset = 0;
10603
10604     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10605         lastoffset = offset;
10606         switch (fTagNo(tvb, offset)) {
10607         case 0: /* errorType */
10608             offset = fContextTaggedError(tvb, pinfo, tree, offset);
10609             break;
10610         case 1: /* firstFailedElementNumber */
10611             offset = fUnsignedTag(tvb, pinfo, tree, offset, "first failed element number: ");
10612             break;
10613         default:
10614             return offset;
10615         }
10616         if (offset == lastoffset) break;     /* nothing happened, exit loop */
10617     }
10618     return offset;
10619 }
10620
10621 static guint
10622 fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10623 {
10624     /* Identical to CreateObjectError */
10625     return fCreateObjectError(tvb, pinfo, tree, offset);
10626 }
10627
10628 static guint
10629 fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10630 {
10631     guint8  tag_no = 0, tag_info = 0;
10632     guint32 lvt = 0;
10633
10634     if (fTagNo(tvb, offset) == 0) {
10635         /* errorType */
10636         offset = fContextTaggedError(tvb, pinfo, tree, offset);
10637         if (fTagNo(tvb, offset) == 1) {
10638             /* listOfVTSessionIdentifiers [OPTIONAL] */
10639             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10640             offset  = fVtCloseRequest(tvb, pinfo, tree, offset);
10641             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10642         }
10643     }
10644     /* should report bad packet if initial tag wasn't 0 */
10645     return offset;
10646 }
10647
10648 static guint
10649 fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10650 {
10651     guint   lastoffset = 0;
10652     guint8  tag_no     = 0, tag_info = 0;
10653     guint32 lvt        = 0;
10654
10655     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10656     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10657         lastoffset = offset;
10658         switch (fTagNo(tvb, offset)) {
10659         case 0: /* errorType */
10660             offset = fContextTaggedError(tvb, pinfo, tree, offset);
10661             break;
10662         case 1: /* firstFailedWriteAttempt */
10663             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10664             offset  = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
10665             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10666             break;
10667         default:
10668             return offset;
10669         }
10670         if (offset == lastoffset) break;     /* nothing happened, exit loop */
10671     }
10672     return offset;
10673 }
10674
10675 static guint
10676 fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10677 {
10678     offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
10679                            "error Class: ", BACnetErrorClass, 64);
10680     return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
10681                          "error Code: ", BACnetErrorCode, 256);
10682 }
10683
10684 static guint
10685 fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service)
10686 {
10687     switch (service) {
10688     case 8:  /* no break here !!!! */
10689     case 9:
10690         offset = fChangeListError(tvb, pinfo, tree, offset);
10691         break;
10692     case 10:
10693         offset = fCreateObjectError(tvb, pinfo, tree, offset);
10694         break;
10695     case 16:
10696         offset = fWritePropertyMultipleError(tvb, pinfo, tree, offset);
10697         break;
10698     case 18:
10699         offset = fConfirmedPrivateTransferError(tvb, pinfo, tree, offset);
10700         break;
10701     case 22:
10702         offset = fVTCloseError(tvb, pinfo, tree, offset);
10703         break;
10704     default:
10705         return fError(tvb, pinfo, tree, offset);
10706     }
10707     return offset;
10708 }
10709
10710 static guint
10711 fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10712 {   /* BACnet-Error-PDU */
10713     /* ASHRAE 135-2001 20.1.7 */
10714
10715     proto_item *tc;
10716     proto_tree *bacapp_tree_control;
10717     guint8      tmp;
10718
10719     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10720     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10721
10722     proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10723                 offset++, 1, ENC_BIG_ENDIAN);
10724     tmp = tvb_get_guint8(tvb, offset);
10725     proto_tree_add_item(bacapp_tree_control, hf_bacapp_service, tvb,
10726                  offset++, 1, ENC_BIG_ENDIAN);
10727     /* Error Handling follows... */
10728     return fBACnetError(tvb, pinfo, bacapp_tree, offset, tmp);
10729 }
10730
10731 static guint
10732 fRejectPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10733 {   /* BACnet-Reject-PDU */
10734     /* ASHRAE 135-2001 20.1.8 */
10735
10736     proto_item *tc;
10737     proto_tree *bacapp_tree_control;
10738
10739     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10740     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10741
10742     proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10743                 offset++, 1, ENC_BIG_ENDIAN);
10744     proto_tree_add_item(bacapp_tree_control, hf_BACnetRejectReason, tvb,
10745                 offset++, 1, ENC_BIG_ENDIAN);
10746     return offset;
10747 }
10748
10749 static guint
10750 fAbortPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10751 {   /* BACnet-Abort-PDU */
10752     /* ASHRAE 135-2001 20.1.9 */
10753
10754     proto_item *tc;
10755     proto_tree *bacapp_tree_control;
10756
10757     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
10758     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10759
10760     proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
10761     proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10762                 offset++, 1, ENC_BIG_ENDIAN);
10763     proto_tree_add_item(bacapp_tree_control, hf_BACnetAbortReason, tvb,
10764                 offset++, 1, ENC_BIG_ENDIAN);
10765     return offset;
10766 }
10767
10768 static guint
10769 do_the_dissection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
10770 {
10771     guint8 flag, bacapp_type;
10772     guint  offset = 0;
10773
10774     flag = (gint) tvb_get_guint8(tvb, 0);
10775     bacapp_type = (flag >> 4) & 0x0f;
10776
10777     if (tvb == NULL) {
10778         return 0;
10779     }
10780
10781     /* ASHRAE 135-2001 20.1.1 */
10782     switch (bacapp_type) {
10783     case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST: /* BACnet-Confirmed-Service-Request */
10784         offset = fConfirmedRequestPDU(tvb, pinfo, tree, offset);
10785         break;
10786     case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:   /* BACnet-Unconfirmed-Request-PDU */
10787         offset = fUnconfirmedRequestPDU(tvb, pinfo, tree, offset);
10788         break;
10789     case BACAPP_TYPE_SIMPLE_ACK:    /* BACnet-Simple-Ack-PDU */
10790         offset = fSimpleAckPDU(tvb, pinfo, tree, offset);
10791         break;
10792     case BACAPP_TYPE_COMPLEX_ACK:   /* BACnet-Complex-Ack-PDU */
10793         offset = fComplexAckPDU(tvb, pinfo, tree, offset);
10794         break;
10795     case BACAPP_TYPE_SEGMENT_ACK:   /* BACnet-SegmentAck-PDU */
10796         offset = fSegmentAckPDU(tvb, pinfo, tree, offset);
10797         break;
10798     case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
10799         offset = fErrorPDU(tvb, pinfo, tree, offset);
10800         break;
10801     case BACAPP_TYPE_REJECT:    /* BACnet-Reject-PDU */
10802         offset = fRejectPDU(tvb, pinfo, tree, offset);
10803         break;
10804     case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
10805         offset = fAbortPDU(tvb, pinfo, tree, offset);
10806         break;
10807     }
10808     return offset;
10809 }
10810
10811 static void
10812 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
10813 {
10814     guint8      flag, bacapp_type;
10815     guint       save_fragmented  = FALSE, data_offset = 0, /*bacapp_apdu_size,*/ fragment = FALSE;
10816     tvbuff_t   *new_tvb          = NULL;
10817     guint       offset           = 0;
10818     guint8      bacapp_seqno     = 0;
10819     guint8      bacapp_service, bacapp_reason/*, bacapp_prop_win_size*/;
10820     guint8      bacapp_invoke_id = 0;
10821     proto_item *ti;
10822     proto_tree *bacapp_tree      = NULL;
10823
10824     gint        svc = 0;
10825     proto_item *tt  = 0;
10826     gint8       ack = 0;
10827
10828     /* Strings for BACnet Statistics */
10829     const gchar errstr[]       = "ERROR: ";
10830     const gchar rejstr[]       = "REJECTED: ";
10831     const gchar abortstr[]     = "ABORTED: ";
10832     const gchar sackstr[]      = " (SimpleAck)";
10833     const gchar cackstr[]      = " (ComplexAck)";
10834     const gchar uconfsreqstr[] = " (Unconfirmed Service Request)";
10835     const gchar confsreqstr[]  = " (Confirmed Service Request)";
10836
10837     col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
10838     col_clear(pinfo->cinfo, COL_INFO);
10839
10840     flag = tvb_get_guint8(tvb, 0);
10841     bacapp_type = (flag >> 4) & 0x0f;
10842
10843     /* show some descriptive text in the INFO column */
10844     col_add_fstr(pinfo->cinfo, COL_INFO, "%-16s",
10845         val_to_str_const(bacapp_type, BACnetTypeName, "# unknown APDU #"));
10846
10847     bacinfo.service_type = NULL;
10848     bacinfo.invoke_id = NULL;
10849     bacinfo.instance_ident = NULL;
10850     bacinfo.object_ident = NULL;
10851
10852     switch (bacapp_type) {
10853     case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
10854         /* segmented messages have 2 additional bytes */
10855         if (flag & BACAPP_SEGMENTED_REQUEST) {
10856             fragment = TRUE;
10857             ack = 0;
10858             /* bacapp_apdu_size = fGetMaxAPDUSize(tvb_get_guint8(tvb, offset + 1)); */ /* has 16 values, reserved are 50 Bytes */
10859             bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
10860             bacapp_seqno = tvb_get_guint8(tvb, offset + 3);
10861             /* bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 4); */
10862             bacapp_service = tvb_get_guint8(tvb, offset + 5);
10863             data_offset = 6;
10864         } else {
10865             bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
10866             bacapp_service = tvb_get_guint8(tvb, offset + 3);
10867         }
10868         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ",
10869                         val_to_str_const(bacapp_service,
10870                                          BACnetConfirmedServiceChoice,
10871                                          bacapp_unknown_service_str),
10872                         bacapp_invoke_id);
10873
10874         updateBacnetInfoValue(BACINFO_INVOKEID,
10875                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10876
10877         updateBacnetInfoValue(BACINFO_SERVICE,
10878                               wmem_strconcat(wmem_packet_scope(),
10879                                              val_to_str_const(bacapp_service,
10880                                                               BACnetConfirmedServiceChoice,
10881                                                               bacapp_unknown_service_str),
10882                                              confsreqstr, NULL));
10883         break;
10884     case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
10885         bacapp_service = tvb_get_guint8(tvb, offset + 1);
10886         col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
10887                         val_to_str_const(bacapp_service,
10888                                          BACnetUnconfirmedServiceChoice,
10889                                          bacapp_unknown_service_str));
10890
10891         updateBacnetInfoValue(BACINFO_SERVICE,
10892                               wmem_strconcat(wmem_packet_scope(),
10893                                              val_to_str_const(bacapp_service,
10894                                                               BACnetUnconfirmedServiceChoice,
10895                                                               bacapp_unknown_service_str),
10896                                              uconfsreqstr, NULL));
10897         break;
10898     case BACAPP_TYPE_SIMPLE_ACK:
10899         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10900         bacapp_service = tvb_get_guint8(tvb, offset + 2);
10901         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10902                         val_to_str_const(bacapp_service,
10903                                          BACnetConfirmedServiceChoice,
10904                                          bacapp_unknown_service_str),
10905                         bacapp_invoke_id);
10906
10907         updateBacnetInfoValue(BACINFO_INVOKEID,
10908                               wmem_strdup_printf(wmem_packet_scope(),
10909                                                  "Invoke ID: %d", bacapp_invoke_id));
10910
10911         updateBacnetInfoValue(BACINFO_SERVICE,
10912                               wmem_strconcat(wmem_packet_scope(),
10913                                              val_to_str_const(bacapp_service,
10914                                                               BACnetConfirmedServiceChoice,
10915                                                               bacapp_unknown_service_str),
10916                                              sackstr, NULL));
10917         break;
10918     case BACAPP_TYPE_COMPLEX_ACK:
10919         /* segmented messages have 2 additional bytes */
10920         if (flag & BACAPP_SEGMENTED_REQUEST) {
10921             fragment = TRUE;
10922             ack = 1;
10923             /* bacapp_apdu_size = fGetMaxAPDUSize(0); */ /* has minimum of 50 Bytes */
10924             bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10925             bacapp_seqno = tvb_get_guint8(tvb, offset + 2);
10926             /* bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 3); */
10927             bacapp_service = tvb_get_guint8(tvb, offset + 4);
10928             data_offset = 5;
10929         } else {
10930             bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10931             bacapp_service = tvb_get_guint8(tvb, offset + 2);
10932         }
10933         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10934                         val_to_str_const(bacapp_service,
10935                                          BACnetConfirmedServiceChoice,
10936                                          bacapp_unknown_service_str),
10937                         bacapp_invoke_id);
10938
10939         updateBacnetInfoValue(BACINFO_INVOKEID,
10940                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10941
10942         updateBacnetInfoValue(BACINFO_SERVICE,
10943                               wmem_strconcat(wmem_packet_scope(),
10944                                              val_to_str_const(bacapp_service,
10945                                                               BACnetConfirmedServiceChoice,
10946                                                               bacapp_unknown_service_str),
10947                                              cackstr, NULL));
10948         break;
10949     case BACAPP_TYPE_SEGMENT_ACK:
10950         /* nothing more to add */
10951         break;
10952     case BACAPP_TYPE_ERROR:
10953         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10954         bacapp_service = tvb_get_guint8(tvb, offset + 2);
10955         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10956                         val_to_str_const(bacapp_service,
10957                                          BACnetConfirmedServiceChoice,
10958                                          bacapp_unknown_service_str),
10959                         bacapp_invoke_id);
10960
10961         updateBacnetInfoValue(BACINFO_INVOKEID,
10962                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10963
10964         updateBacnetInfoValue(BACINFO_SERVICE,
10965                               wmem_strconcat(wmem_packet_scope(),
10966                                              errstr,
10967                                              val_to_str_const(bacapp_service,
10968                                                               BACnetConfirmedServiceChoice,
10969                                                               bacapp_unknown_service_str),
10970                                              NULL));
10971         break;
10972     case BACAPP_TYPE_REJECT:
10973         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10974         bacapp_reason = tvb_get_guint8(tvb, offset + 2);
10975         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10976                         val_to_split_str(bacapp_reason,
10977                                          64,
10978                                          BACnetRejectReason,
10979                                          ASHRAE_Reserved_Fmt,
10980                                          Vendor_Proprietary_Fmt), bacapp_invoke_id);
10981
10982         updateBacnetInfoValue(BACINFO_INVOKEID,
10983                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10984
10985         updateBacnetInfoValue(BACINFO_SERVICE,
10986                               wmem_strconcat(wmem_packet_scope(), rejstr,
10987                                              val_to_split_str(bacapp_reason, 64,
10988                                                               BACnetRejectReason,
10989                                                               ASHRAE_Reserved_Fmt,
10990                                                               Vendor_Proprietary_Fmt),
10991                                              NULL));
10992         break;
10993     case BACAPP_TYPE_ABORT:
10994         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10995         bacapp_reason = tvb_get_guint8(tvb, offset + 2);
10996         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10997                         val_to_split_str(bacapp_reason,
10998                                          64,
10999                                          BACnetAbortReason,
11000                                          ASHRAE_Reserved_Fmt,
11001                                          Vendor_Proprietary_Fmt), bacapp_invoke_id);
11002
11003         updateBacnetInfoValue(BACINFO_INVOKEID,
11004                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
11005
11006         updateBacnetInfoValue(BACINFO_SERVICE,
11007                               wmem_strconcat(wmem_packet_scope(), abortstr,
11008                                              val_to_split_str(bacapp_reason,
11009                                                               64,
11010                                                               BACnetAbortReason,
11011                                                               ASHRAE_Reserved_Fmt,
11012                                                               Vendor_Proprietary_Fmt),
11013                                              NULL));
11014         break;
11015         /* UNKNOWN */
11016     default:
11017         /* nothing more to add */
11018         break;
11019     }
11020
11021     save_fragmented = pinfo->fragmented;
11022
11023     ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, ENC_NA);
11024     bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
11025
11026     if (!fragment)
11027         do_the_dissection(tvb, pinfo, bacapp_tree);
11028     else
11029         fStartConfirmed(tvb, pinfo, bacapp_tree, offset, ack, &svc, &tt);
11030             /* not resetting the offset so the remaining can be done */
11031
11032     if (fragment) { /* fragmented */
11033         fragment_head *frag_msg;
11034
11035         pinfo->fragmented = TRUE;
11036
11037         frag_msg = fragment_add_seq_check(&msg_reassembly_table,
11038             tvb, data_offset,
11039             pinfo,
11040             bacapp_invoke_id,      /* ID for fragments belonging together */
11041             NULL,
11042             bacapp_seqno,          /* fragment sequence number */
11043             tvb_reported_length_remaining(tvb, data_offset), /* fragment length - to the end */
11044             flag & BACAPP_MORE_SEGMENTS); /* Last fragment reached? */
11045         new_tvb = process_reassembled_data(tvb, data_offset, pinfo,
11046                 "Reassembled BACapp", frag_msg, &msg_frag_items,
11047                 NULL, tree);
11048
11049         if (new_tvb) { /* Reassembled */
11050             col_append_str(pinfo->cinfo, COL_INFO,
11051                            " (Message Reassembled)");
11052         } else { /* Not last packet of reassembled Short Message */
11053             col_append_fstr(pinfo->cinfo, COL_INFO,
11054                             " (Message fragment %u)", bacapp_seqno);
11055         }
11056         if (new_tvb) { /* take it all */
11057             switch (bacapp_type) {
11058             case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
11059                 fContinueConfirmedRequestPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
11060                 break;
11061             case BACAPP_TYPE_COMPLEX_ACK:
11062                 fContinueComplexAckPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
11063                 break;
11064             default:
11065                 /* do nothing */
11066                 break;
11067             }
11068         }
11069     }
11070
11071     pinfo->fragmented = save_fragmented;
11072
11073     /* tapping */
11074     tap_queue_packet(bacapp_tap, pinfo, &bacinfo);
11075 }
11076
11077 static void
11078 bacapp_init_routine(void)
11079 {
11080     reassembly_table_init(&msg_reassembly_table,
11081                           &addresses_reassembly_table_functions);
11082 }
11083
11084 void
11085 proto_register_bacapp(void)
11086 {
11087     static hf_register_info hf[] = {
11088         { &hf_bacapp_type,
11089           { "APDU Type",           "bacapp.type",
11090             FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, NULL, HFILL }
11091         },
11092         { &hf_bacapp_pduflags,
11093           { "PDU Flags",          "bacapp.pduflags",
11094             FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }
11095         },
11096         { &hf_bacapp_SEG,
11097           { "Segmented Request",           "bacapp.segmented_request",
11098             FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, NULL, HFILL }
11099         },
11100         { &hf_bacapp_MOR,
11101           { "More Segments",           "bacapp.more_segments",
11102             FT_BOOLEAN, 8, TFS(&more_follow), 0x04, "More Segments Follow", HFILL }
11103         },
11104         { &hf_bacapp_SA,
11105           { "SA",           "bacapp.SA",
11106             FT_BOOLEAN, 8, TFS(&segmented_accept), 0x02, "Segmented Response accepted", HFILL }
11107         },
11108         { &hf_bacapp_max_adpu_size,
11109           { "Size of Maximum ADPU accepted",           "bacapp.max_adpu_size",
11110             FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, NULL, HFILL }
11111         },
11112         { &hf_bacapp_response_segments,
11113           { "Max Response Segments accepted",           "bacapp.response_segments",
11114             FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, NULL, HFILL }
11115         },
11116         { &hf_bacapp_objectType,
11117           { "Object Type",           "bacapp.objectType",
11118             FT_UINT32, BASE_DEC, VALS(BACnetObjectType), 0xffc00000, NULL, HFILL }
11119         },
11120         { &hf_bacapp_instanceNumber,
11121           { "Instance Number",           "bacapp.instance_number",
11122             FT_UINT32, BASE_DEC, NULL, 0x003fffff, NULL, HFILL }
11123         },
11124         { &hf_BACnetPropertyIdentifier,
11125           { "Property Identifier", "bacapp.property_identifier",
11126             FT_UINT32, BASE_DEC, VALS(BACnetPropertyIdentifier), 0, NULL, HFILL }
11127         },
11128         { &hf_BACnetVendorIdentifier,
11129           { "Vendor Identifier", "bacapp.vendor_identifier",
11130             FT_UINT16, BASE_DEC|BASE_EXT_STRING, &BACnetVendorIdentifiers_ext, 0, NULL, HFILL }
11131         },
11132         { &hf_BACnetRestartReason,
11133           { "Restart Reason", "bacapp.restart_reason",
11134             FT_UINT8, BASE_DEC, VALS(BACnetRestartReason), 0, NULL, HFILL }
11135         },
11136         { &hf_bacapp_invoke_id,
11137           { "Invoke ID",           "bacapp.invoke_id",
11138             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11139         },
11140         { &hf_bacapp_sequence_number,
11141           { "Sequence Number",           "bacapp.sequence_number",
11142             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11143         },
11144         { &hf_bacapp_window_size,
11145           { "Proposed Window Size",           "bacapp.window_size",
11146             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11147         },
11148         { &hf_bacapp_service,
11149           { "Service Choice",           "bacapp.confirmed_service",
11150             FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, NULL, HFILL }
11151         },
11152         { &hf_bacapp_uservice,
11153           { "Unconfirmed Service Choice",           "bacapp.unconfirmed_service",
11154             FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, NULL, HFILL }
11155         },
11156         { &hf_bacapp_NAK,
11157           { "NAK",           "bacapp.NAK",
11158             FT_BOOLEAN, 8, NULL, 0x02, "negative ACK", HFILL }
11159         },
11160         { &hf_bacapp_SRV,
11161           { "SRV",           "bacapp.SRV",
11162             FT_BOOLEAN, 8, NULL, 0x01, "Server", HFILL }
11163         },
11164         { &hf_Device_Instance_Range_Low_Limit,
11165           { "Device Instance Range Low Limit", "bacapp.who_is.low_limit",
11166             FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
11167         },
11168         { &hf_Device_Instance_Range_High_Limit,
11169           { "Device Instance Range High Limit", "bacapp.who_is.high_limit",
11170             FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
11171         },
11172         { &hf_BACnetRejectReason,
11173           { "Reject Reason",           "bacapp.reject_reason",
11174             FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, NULL, HFILL }
11175         },
11176         { &hf_BACnetAbortReason,
11177           { "Abort Reason",           "bacapp.abort_reason",
11178             FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, NULL, HFILL }
11179         },
11180         { &hf_BACnetApplicationTagNumber,
11181           { "Application Tag Number",
11182             "bacapp.application_tag_number",
11183             FT_UINT8, BASE_DEC, VALS(BACnetApplicationTagNumber), 0xF0,
11184             NULL, HFILL }
11185         },
11186         { &hf_BACnetContextTagNumber,
11187           { "Context Tag Number",
11188             "bacapp.context_tag_number",
11189             FT_UINT8, BASE_DEC, NULL, 0xF0,
11190             NULL, HFILL }
11191         },
11192         { &hf_BACnetExtendedTagNumber,
11193           { "Extended Tag Number",
11194             "bacapp.extended_tag_number",
11195             FT_UINT8, BASE_DEC, NULL, 0,
11196             NULL, HFILL }
11197         },
11198         { &hf_BACnetNamedTag,
11199           { "Named Tag",
11200             "bacapp.named_tag",
11201             FT_UINT8, BASE_DEC, VALS(BACnetTagNames), 0x07,
11202             NULL, HFILL }
11203         },
11204         { &hf_BACnetCharacterSet,
11205           { "String Character Set",
11206             "bacapp.string_character_set",
11207             FT_UINT8, BASE_DEC, VALS(BACnetCharacterSet), 0,
11208             NULL, HFILL }
11209         },
11210         { &hf_BACnetTagClass,
11211           { "Tag Class",           "bacapp.tag_class",
11212             FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, NULL, HFILL }
11213         },
11214         { &hf_bacapp_tag_lvt,
11215           { "Length Value Type",
11216             "bacapp.LVT",
11217             FT_UINT8, BASE_DEC, NULL, 0,
11218             NULL, HFILL }
11219         },
11220         { &hf_bacapp_tag_ProcessId,
11221           { "ProcessIdentifier",           "bacapp.processId",
11222             FT_UINT32, BASE_DEC, NULL, 0, "Process Identifier", HFILL }
11223         },
11224         { &hf_bacapp_tag_IPV4,
11225           { "IPV4",           "bacapp.IPV4",
11226             FT_IPv4, BASE_NONE, NULL, 0, "IP-Address", HFILL }
11227         },
11228         { &hf_bacapp_tag_IPV6,
11229           { "IPV6",           "bacapp.IPV6",
11230             FT_IPv6, BASE_NONE, NULL, 0, "IP-Address", HFILL }
11231         },
11232         { &hf_bacapp_tag_PORT,
11233           { "Port",           "bacapp.Port",
11234             FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
11235         },
11236         {&hf_msg_fragments,
11237          {"Message fragments", "bacapp.fragments",
11238           FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11239         {&hf_msg_fragment,
11240          {"Message fragment", "bacapp.fragment",
11241           FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11242         {&hf_msg_fragment_overlap,
11243          {"Message fragment overlap", "bacapp.fragment.overlap",
11244           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11245         {&hf_msg_fragment_overlap_conflicts,
11246          {"Message fragment overlapping with conflicting data",
11247           "bacapp.fragment.overlap.conflicts",
11248           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11249         {&hf_msg_fragment_multiple_tails,
11250          {"Message has multiple tail fragments",
11251           "bacapp.fragment.multiple_tails",
11252           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11253         {&hf_msg_fragment_too_long_fragment,
11254          {"Message fragment too long", "bacapp.fragment.too_long_fragment",
11255           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11256         {&hf_msg_fragment_error,
11257          {"Message defragmentation error", "bacapp.fragment.error",
11258           FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11259         {&hf_msg_fragment_count,
11260          {"Message fragment count", "bacapp.fragment.count",
11261           FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
11262         {&hf_msg_reassembled_in,
11263          {"Reassembled in", "bacapp.reassembled.in",
11264           FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11265         {&hf_msg_reassembled_length,
11266          {"Reassembled BACapp length", "bacapp.reassembled.length",
11267           FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }
11268     };
11269     static gint *ett[] = {
11270         &ett_bacapp,
11271         &ett_bacapp_control,
11272         &ett_bacapp_tag,
11273         &ett_bacapp_list,
11274         &ett_bacapp_value,
11275         &ett_msg_fragment,
11276         &ett_msg_fragments
11277
11278     };
11279
11280     static ei_register_info ei[] = {
11281         { &ei_bacapp_bad_length, { "bacapp.bad_length", PI_MALFORMED, PI_ERROR, "Wrong length indicated", EXPFILL }},
11282     };
11283
11284     expert_module_t* expert_bacapp;
11285
11286     proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
11287                                            "BACapp", "bacapp");
11288
11289     proto_register_field_array(proto_bacapp, hf, array_length(hf));
11290     proto_register_subtree_array(ett, array_length(ett));
11291     expert_bacapp = expert_register_protocol(proto_bacapp);
11292     expert_register_field_array(expert_bacapp, ei, array_length(ei));
11293     register_dissector("bacapp", dissect_bacapp, proto_bacapp);
11294     register_init_routine(&bacapp_init_routine);
11295
11296     bacapp_dissector_table = register_dissector_table("bacapp.vendor_identifier",
11297                                                       "BACapp Vendor Identifier",
11298                                                       FT_UINT8, BASE_HEX);
11299
11300     /* Register BACnet Statistic trees */
11301     register_bacapp_stat_trees();
11302     bacapp_tap = register_tap("bacapp"); /* BACnet statistics tap */
11303 }
11304
11305 /*
11306  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
11307  *
11308  * Local variables:
11309  * c-basic-offset: 4
11310  * tab-width: 8
11311  * indent-tabs-mode: nil
11312  * End:
11313  *
11314  * vi: set shiftwidth=4 tabstop=8 expandtab:
11315  * :indentSize=4:tabSize=8:noTabs=true:
11316  */