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