bacapp: cleanup and remove some add_text
[metze/wireshark/wip.git] / epan / dissectors / packet-bacapp.c
1 /* packet-bacapp.c
2  * Routines for BACnet (APDU) dissection
3  * Copyright 2001, Hartmut Mueller <hartmut[AT]abmlinux.org>, FH Dortmund
4  * Enhanced by Steve Karg, 2005, <skarg[AT]users.sourceforge.net>, Atlanta
5  * Enhanced by Herbert Lischka, 2005, <lischka[AT]kieback-peter.de>, Berlin
6  * Enhanced by Felix Kraemer, 2010, <sauter-cumulus[AT]de.sauter-bc.com>,
7  *  Sauter-Cumulus GmbH, Freiburg
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald[AT]wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
27
28 #include "config.h"
29
30 #include <epan/packet.h>
31 #include <epan/to_str.h>
32 #include <epan/reassemble.h>
33 #include <epan/expert.h>
34 #include <epan/stats_tree.h>
35 #include "packet-bacapp.h"
36
37 static int bacapp_tap = -1;
38
39 /* formerly bacapp.h  contains definitions and forward declarations */
40
41 /* BACnet PDU Types */
42 #define BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST                   0
43 #define BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST                 1
44 #define BACAPP_TYPE_SIMPLE_ACK                                  2
45 #define BACAPP_TYPE_COMPLEX_ACK                                 3
46 #define BACAPP_TYPE_SEGMENT_ACK                                 4
47 #define BACAPP_TYPE_ERROR                                       5
48 #define BACAPP_TYPE_REJECT                                      6
49 #define BACAPP_TYPE_ABORT                                       7
50 #define MAX_BACAPP_TYPE                                         8
51
52 #define BACAPP_SEGMENTED_REQUEST 0x08
53 #define BACAPP_MORE_SEGMENTS 0x04
54 #define BACAPP_SEGMENTED_RESPONSE 0x02
55 #define BACAPP_SEGMENT_NAK 0x02
56 #define BACAPP_SENT_BY 0x01
57
58
59 /**
60  * dissect_bacapp ::= CHOICE {
61  *  confirmed-request-PDU       [0] BACnet-Confirmed-Request-PDU,
62  *  unconfirmed-request-PDU     [1] BACnet-Unconfirmed-Request-PDU,
63  *  simpleACK-PDU               [2] BACnet-SimpleACK-PDU,
64  *  complexACK-PDU              [3] BACnet-ComplexACK-PDU,
65  *  segmentACK-PDU              [4] BACnet-SegmentACK-PDU,
66  *  error-PDU                   [5] BACnet-Error-PDU,
67  *  reject-PDU                  [6] BACnet-Reject-PDU,
68  *  abort-PDU                   [7] BACnet-Abort-PDU
69  * }
70  * @param tvb the tv buffer of the current data
71  * @param pinfo the packet info of the current data
72  * @param tree the tree to append this item to
73  **/
74 static void
75 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
76
77 /**
78  * ConfirmedRequest-PDU ::= SEQUENCE {
79  *  pdu-type                    [0] Unsigned (0..15), -- 0 for this PDU Type
80  *  segmentedMessage            [1] BOOLEAN,
81  *  moreFollows                 [2] BOOLEAN,
82  *  segmented-response-accepted [3] BOOLEAN,
83  *  reserved                    [4] Unsigned (0..3), -- must be set zero
84  *  max-segments-accepted       [5] Unsigned (0..7), -- as per 20.1.2.4
85  *  max-APDU-length-accepted    [5] Unsigned (0..15), -- as per 20.1.2.5
86  *  invokeID                    [6] Unsigned (0..255),
87  *  sequence-number             [7] Unsigned (0..255) OPTIONAL, -- only if segmented msg
88  *  proposed-window-size        [8] Unsigned (0..127) OPTIONAL, -- only if segmented msg
89  *  service-choice              [9] BACnetConfirmedServiceChoice,
90  *  service-request             [10] BACnet-Confirmed-Service-Request OPTIONAL
91  * }
92  * @param tvb the tv buffer of the current data
93  * @param pinfo the packet info of the current data
94  * @param tree the tree to append this item to
95  * @param offset the offset in the tvb
96  * @return modified offset
97  */
98 static guint
99 fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
100
101 /**
102  * @param tvb the tv buffer of the current data
103  * @param pinfo the packet info of the current data
104  * @param tree the tree to append this item to
105  * @param offset the offset in the tvb
106  * @param ack - indocates whether working on request or ack
107  * @param svc - output variable to return service choice
108  * @param tt  - output varable to return service choice item
109  * @return modified offset
110  */
111 static guint
112 fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 ack,
113                 gint *svc, proto_item **tt);
114
115 /**
116  * Unconfirmed-Request-PDU ::= SEQUENCE {
117  *  pdu-type        [0] Unsigned (0..15), -- 1 for this PDU type
118  *  reserved        [1] Unsigned (0..15), -- must be set zero
119  *  service-choice  [2] BACnetUnconfirmedServiceChoice,
120  *  service-request [3] BACnetUnconfirmedServiceRequest -- Context-specific tags 0..3 are NOT used in header encoding
121  * }
122  * @param tvb the tv buffer of the current data
123  * @param pinfo the packet info of the current data
124  * @param tree the tree to append this item to
125  * @param offset the offset in the tvb
126  * @return modified offset
127  */
128 static guint
129 fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
130
131 /**
132  * SimpleACK-PDU ::= SEQUENCE {
133  *  pdu-type            [0] Unsigned (0..15), -- 2 for this PDU type
134  *  reserved            [1] Unsigned (0..15), -- must be set zero
135  *  invokeID            [2] Unsigned (0..255),
136  *  service-ACK-choice  [3] BACnetUnconfirmedServiceChoice -- Context-specific tags 0..3 are NOT used in header encoding
137  * }
138  * @param tvb the tv buffer of the current data
139  * @param pinfo the packet info of the current data
140  * @param tree the tree to append this item to
141  * @param offset the offset in the tvb
142  * @return modified offset
143  */
144 static guint
145 fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
146
147 /**
148  * ComplexACK-PDU ::= SEQUENCE {
149  *  pdu-type                [0] Unsigned (0..15), -- 3 for this PDU Type
150  *  segmentedMessage        [1] BOOLEAN,
151  *  moreFollows             [2] BOOLEAN,
152  *  reserved                [3] Unsigned (0..3), -- must be set zero
153  *  invokeID                [4] Unsigned (0..255),
154  *  sequence-number         [5] Unsigned (0..255) OPTIONAL, -- only if segmented msg
155  *  proposed-window-size    [6] Unsigned (0..127) OPTIONAL, -- only if segmented msg
156  *  service-ACK-choice      [7] BACnetConfirmedServiceChoice,
157  *  service-ACK             [8] BACnet-Confirmed-Service-Request  -- Context-specific tags 0..8 are NOT used in header encoding
158  * }
159  * @param tvb the tv buffer of the current data
160  * @param pinfo the packet info of the current data
161  * @param tree the tree to append this item to
162  * @param offset the offset in the tvb
163  * @return modified offset
164  */
165 static guint
166 fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
167
168 /**
169  * SegmentACK-PDU ::= SEQUENCE {
170  *  pdu-type                [0] Unsigned (0..15), -- 4 for this PDU Type
171  *  reserved                [1] Unsigned (0..3), -- must be set zero
172  *  negative-ACK            [2] BOOLEAN,
173  *  server                  [3] BOOLEAN,
174  *  original-invokeID       [4] Unsigned (0..255),
175  *  sequence-number         [5] Unsigned (0..255),
176  *  actual-window-size      [6] Unsigned (0..127)
177  * }
178  * @param tvb the tv buffer of the current data
179  * @param pinfo the packet info of the current data
180  * @param tree the tree to append this item to
181  * @param offset the offset in the tvb
182  * @return modified offset
183  */
184 static guint
185 fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
186
187 /**
188  * Error-PDU ::= SEQUENCE {
189  *  pdu-type                [0] Unsigned (0..15), -- 5 for this PDU Type
190  *  reserved                [1] Unsigned (0..3), -- must be set zero
191  *  original-invokeID       [2] Unsigned (0..255),
192  *  error-choice            [3] BACnetConfirmedServiceChoice,
193  *  error                   [4] BACnet-Error
194  * }
195  * @param tvb the tv buffer of the current data
196  * @param pinfo the packet info of the current data
197  * @param tree the tree to append this item to
198  * @param offset the offset in the tvb
199  * @return modified offset
200  */
201 static guint
202 fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
203
204 /**
205  * Reject-PDU ::= SEQUENCE {
206  *  pdu-type                [0] Unsigned (0..15), -- 6 for this PDU Type
207  *  reserved                [1] Unsigned (0..3), -- must be set zero
208  *  original-invokeID       [2] Unsigned (0..255),
209  *  reject-reason           [3] BACnetRejectReason
210  * }
211  * @param tvb the tv buffer of the current data
212  * @param pinfo the packet info of the current data
213  * @param tree the tree to append this item to
214  * @param offset the offset in the tvb
215  * @return modified offset
216  */
217 static guint
218 fRejectPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
219
220 /**
221  * Abort-PDU ::= SEQUENCE {
222  *  pdu-type                [0] Unsigned (0..15), -- 7 for this PDU Type
223  *  reserved                [1] Unsigned (0..3), -- must be set zero
224  *  server                  [2] BOOLEAN,
225  *  original-invokeID       [3] Unsigned (0..255),
226  *  abort-reason            [4] BACnetAbortReason
227  * }
228  * @param tvb the tv buffer of the current data
229  * @param pinfo the packet info of the current data
230  * @param tree the tree to append this item to
231  * @param offset the offset in the tvb
232  * @return modified offset
233  */
234 static guint
235 fAbortPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
236
237 /**
238  * 20.2.4, adds the label with max 64Bit unsigned Integer Value to tree
239  * @param tvb the tv buffer of the current data
240  * @param pinfo the packet info of the current data
241  * @param tree the tree to append this item to
242  * @param offset the offset in the tvb
243  * @param label the label of this item
244  * @return modified offset
245  */
246 static guint
247 fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
248
249 /**
250  * 20.2.5, adds the label with max 64Bit signed Integer Value to tree
251  * @param tvb the tv buffer of the current data
252  * @param pinfo the packet info of the current data
253  * @param tree the tree to append this item to
254  * @param offset the offset in the tvb
255  * @param label the label of this item
256  * @return modified offset
257  */
258 static guint
259 fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
260
261 /**
262  * 20.2.8, adds the label with Octet String to tree; if lvt == 0 then lvt = restOfFrame
263  * @param tvb the tv buffer of the current data
264  * @param pinfo the packet info of the current data
265  * @param tree the tree to append this item to
266  * @param offset the offset in the tvb
267  * @param label the label of this item
268  * @param lvt length of String
269  * @return modified offset
270  */
271 static guint
272 fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt);
273
274 /**
275  * 20.2.12, adds the label with Date Value to tree
276  * @param tvb the tv buffer of the current data
277  * @param pinfo the packet info of the current data
278  * @param tree the tree to append this item to
279  * @param offset the offset in the tvb
280  * @param label the label of this item
281  * @return modified offset
282  */
283 static guint
284 fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
285
286 /**
287  * 20.2.13, adds the label with Time Value to tree
288  * @param tvb the tv buffer of the current data
289  * @param pinfo the packet info of the current data
290  * @param tree the tree to append this item to
291  * @param offset the offset in the tvb
292  * @param label the label of this item
293  * @return modified offset
294  */
295 static guint
296 fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
297
298 /**
299  * 20.2.14, adds Object Identifier to tree
300  * use BIG ENDIAN: Bits 31..22 Object Type, Bits 21..0 Instance Number
301  * @param tvb the tv buffer of the current data
302  * @param pinfo the packet info of the current data
303  * @param tree the tree to append this item to
304  * @param offset the offset in the tvb
305  * @return modified offset
306  */
307 static guint
308 fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
309
310 /**
311  * BACnet-Confirmed-Service-Request ::= CHOICE {
312  * }
313  * @param tvb the tv buffer of the current data
314  * @param pinfo the packet info of the current data
315  * @param tree the tree to append this item to
316  * @param offset the offset in the tvb
317  * @param service_choice the service choice
318  * @return offset
319  */
320 static guint
321 fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
322
323 /**
324  * BACnet-Confirmed-Service-ACK ::= CHOICE {
325  * }
326  * @param tvb the tv buffer of the current data
327  * @param pinfo the packet info of the current data
328  * @param tree the tree to append this item to
329  * @param offset the offset in the tvb
330  * @param service_choice the service choice
331  * @return offset
332  */
333 static guint
334 fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
335
336 /**
337  * AcknowledgeAlarm-Request ::= SEQUENCE {
338  *  acknowledgingProcessIdentifier [0] Unsigned32,
339  *  eventObjectIdentifier          [1] BACnetObjectIdentifer,
340  *  eventStateAcknowledge          [2] BACnetEventState,
341  *  timeStamp                      [3] BACnetTimeStamp,
342  *  acknowledgementSource          [4] Character String,
343  *  timeOfAcknowledgement          [5] BACnetTimeStamp
344  * }
345  * @param tvb the tv buffer of the current data
346  * @param pinfo the packet info of the current data
347  * @param tree the tree to append this item to
348  * @param offset the offset in the tvb
349  * @return modified offset
350  */
351 static guint
352 fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
353
354 /**
355  * ConfirmedCOVNotification-Request ::= SEQUENCE {
356  *  subscriberProcessIdentifier [0] Unsigned32,
357  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
358  *  monitoredObjectIdentifier   [2] BACnetObjectIdentifer,
359  *  timeRemaining               [3] unsigned,
360  *  listOfValues                [4] SEQUENCE OF BACnetPropertyValues
361  * }
362  * @param tvb the tv buffer of the current data
363  * @param pinfo the packet info of the current data
364  * @param tree the tree to append this item to
365  * @param offset the offset in the tvb
366  * @return modified offset
367  */
368 static guint
369 fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
370
371 /**
372  * ConfirmedEventNotification-Request ::= SEQUENCE {
373  *  ProcessIdentifier           [0] Unsigned32,
374  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
375  *  eventObjectIdentifier       [2] BACnetObjectIdentifer,
376  *  timeStamp                   [3] BACnetTimeStamp,
377  *  notificationClass           [4] unsigned,
378  *  priority                    [5] unsigned8,
379  *  eventType                   [6] BACnetEventType,
380  *  messageText                 [7] CharacterString OPTIONAL,
381  *  notifyType                  [8] BACnetNotifyType,
382  *  ackRequired                 [9] BOOLEAN OPTIONAL,
383  *  fromState                  [10] BACnetEventState OPTIONAL,
384  *  toState                    [11] BACnetEventState,
385  *  eventValues                [12] BACnetNotificationParameters OPTIONAL
386  * }
387  * @param tvb the tv buffer of the current data
388  * @param pinfo the packet info of the current data
389  * @param tree the tree to append this item to
390  * @param offset the offset in the tvb
391  * @return modified offset
392  */
393 static guint
394 fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo,  proto_tree *tree, guint offset);
395
396 /**
397  * GetAlarmSummary-ACK ::= SEQUENCE OF SEQUENCE {
398  *  objectIdentifier         BACnetObjectIdentifer,
399  *  alarmState               BACnetEventState,
400  *  acknowledgedTransitions  BACnetEventTransitionBits
401  * }
402  * @param tvb the tv buffer of the current data
403  * @param pinfo the packet info of the current data
404  * @param tree the tree to append this item to
405  * @param offset the offset in the tvb
406  * @return modified offset
407  */
408 static guint
409 fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
410
411 /**
412  * GetEnrollmentSummary-Request ::= SEQUENCE {
413  *  acknowledgmentFilter    [0] ENUMERATED {
414  *      all       (0),
415  *      acked     (1),
416  *      not-acked (2)
417  *      },
418  *  enrollmentFilter        [1] BACnetRecipientProcess OPTIONAL,
419  *  eventStateFilter        [2] ENUMERATED {
420  *      offnormal (0),
421  *      fault     (1),
422  *      normal    (2),
423  *      all       (3),
424  *      active    (4)
425  *      },
426  *  eventTypeFilter         [3] BACnetEventType OPTIONAL,
427  *  priorityFilter          [4] SEQUENCE {
428  *      minPriority [0] Unsigned8,
429  *      maxPriority [1] Unsigned8
430  *      } OPTIONAL,
431  *  notificationClassFilter [5] Unsigned OPTIONAL
432  * }
433  * @param tvb the tv buffer of the current data
434  * @param pinfo the packet info of the current data
435  * @param tree the tree to append this item to
436  * @param offset the offset in the tvb
437  * @return modified offset
438  */
439 static guint
440 fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
441
442 /**
443  * GetEnrollmentSummary-ACK ::= SEQUENCE OF SEQUENCE {
444  *  objectIdentifier    BACnetObjectIdentifer,
445  *  eventType           BACnetEventType,
446  *  eventState          BACnetEventState,
447  *  priority            Unsigned8,
448  *  notificationClass   Unsigned OPTIONAL
449  * }
450  * @param tvb the tv buffer of the current data
451  * @param pinfo the packet info of the current data
452  * @param tree the tree to append this item to
453  * @param offset the offset in the tvb
454  * @return modified offset
455  */
456 static guint
457 fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
458
459 /**
460  * GetEventInformation-Request ::= SEQUENCE {
461  *  lastReceivedObjectIdentifier    [0] BACnetObjectIdentifer
462  * }
463  * @param tvb the tv buffer of the current data
464  * @param pinfo the packet info of the current data
465  * @param tree the tree to append this item to
466  * @param offset the offset in the tvb
467  * @return modified offset
468  */
469 static guint
470 fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
471
472 /**
473  * GetEventInformation-ACK ::= SEQUENCE {
474  *  listOfEventSummaries [0] listOfEventSummaries,
475  *  moreEvents           [1] BOOLEAN
476  * }
477  * @param tvb the tv buffer of the current data
478  * @param pinfo the packet info of the current data
479  * @param tree the tree to append this item to
480  * @param offset the offset in the tvb
481  * @return modified offset
482  */
483 static guint
484 fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
485
486 /**
487  * LifeSafetyOperation-Request ::= SEQUENCE {
488  *  requestingProcessIdentifier [0] Unsigned32
489  *  requestingSource            [1] CharacterString
490  *  request                     [2] BACnetLifeSafetyOperation
491  *  objectIdentifier            [3] BACnetObjectIdentifier OPTIONAL
492  * }
493  * @param tvb the tv buffer of the current data
494  * @param pinfo the packet info of the current data
495  * @param tree the tree to append this item to
496  * @param offset the offset in the tvb
497  * @return modified offset
498  */
499 static guint
500 fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
501
502 /**
503  * SubscribeCOV-Request ::= SEQUENCE {
504  *  subscriberProcessIdentifier [0] Unsigned32
505  *  monitoredObjectIdentifier   [1] BACnetObjectIdentifier
506  *  issueConfirmedNotifications [2] BOOLEAN OPTIONAL
507  *  lifetime                    [3] Unsigned OPTIONAL
508  * }
509  * @param tvb the tv buffer of the current data
510  * @param pinfo the packet info of the current data
511  * @param tree the tree to append this item to
512  * @param offset the offset in the tvb
513  * @return modified offset
514  */
515 static guint
516 fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
517
518 /**
519  * SubscribeCOVProperty-Request ::= SEQUENCE {
520  *  subscriberProcessIdentifier [0] Unsigned32
521  *  monitoredObjectIdentifier   [1] BACnetObjectIdentifier
522  *  issueConfirmedNotifications [2] BOOLEAN OPTIONAL
523  *  lifetime                    [3] Unsigned OPTIONAL
524  *  monitoredPropertyIdentifier [4] BACnetPropertyReference OPTIONAL
525  *  covIncrement                [5] Unsigned OPTIONAL
526  * }
527  * @param tvb the tv buffer of the current data
528  * @param pinfo the packet info of the current data
529  * @param tree the tree to append this item to
530  * @param offset the offset in the tvb
531  * @return modified offset
532  */
533 static guint
534 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
535
536 /**
537  * AtomicReadFile-Request ::= SEQUENCE {
538  *  fileIdentifier  BACnetObjectIdentifier,
539  *  accessMethod    CHOICE {
540  *      streamAccess    [0] SEQUENCE {
541  *          fileStartPosition   INTEGER,
542  *          requestedOctetCount Unsigned
543  *          },
544  *      recordAccess    [1] SEQUENCE {
545  *          fileStartRecord      INTEGER,
546  *          requestedRecordCount Unsigned
547  *          }
548  *      }
549  * }
550  * @param tvb the tv buffer of the current data
551  * @param pinfo the packet info of the current data
552  * @param tree the tree to append this item to
553  * @param offset the offset in the tvb
554  * @return modified offset
555  */
556 static guint
557 fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
558
559 /**
560  * AtomicWriteFile-ACK ::= SEQUENCE {
561  *  endOfFile   BOOLEAN,
562  *  accessMethod    CHOICE {
563  *      streamAccess    [0] SEQUENCE {
564  *          fileStartPosition   INTEGER,
565  *          fileData            OCTET STRING
566  *          },
567  *      recordAccess    [1] SEQUENCE {
568  *          fileStartRecord     INTEGER,
569  *          returnedRecordCount Unsigned,
570  *          fileRecordData      SEQUENCE OF OCTET STRING
571  *          }
572  *      }
573  * }
574  * @param tvb the tv buffer of the current data
575  * @param pinfo the packet info of the current data
576  * @param tree the tree to append this item to
577  * @param offset the offset in the tvb
578  * @return modified offset
579  */
580 static guint
581 fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
582
583 /**
584  * AtomicWriteFile-Request ::= SEQUENCE {
585  *  fileIdentifier  BACnetObjectIdentifier,
586  *  accessMethod    CHOICE {
587  *      streamAccess    [0] SEQUENCE {
588  *          fileStartPosition  INTEGER,
589  *          fileData           OCTET STRING
590  *          },
591  *      recordAccess    [1] SEQUENCE {
592  *          fileStartRecord    INTEGER,
593  *          recordCount        Unsigned,
594  *          fileRecordData     SEQUENCE OF OCTET STRING
595  *          }
596  *      }
597  * }
598  * @param tvb the tv buffer of the current data
599  * @param pinfo the packet info of the current data
600  * @param tree the tree to append this item to
601  * @param offset the offset in the tvb
602  * @return modified offset
603  */
604 static guint
605 fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
606
607 /**
608  * AtomicWriteFile-ACK ::= SEQUENCE {
609  *      fileStartPosition [0] INTEGER,
610  *      fileStartRecord   [1] INTEGER,
611  * }
612  * @param tvb the tv buffer of the current data
613  * @param pinfo the packet info of the current data
614  * @param tree the tree to append this item to
615  * @param offset the offset in the tvb
616  * @return modified offset
617  */
618 static guint
619 fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
620
621 /**
622  * AddListElement-Request ::= SEQUENCE {
623  *  objectIdentifier   [0] BACnetObjectIdentifier,
624  *  propertyIdentifier [1] BACnetPropertyIdentifier,
625  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
626  *  listOfElements     [3] ABSTRACT-SYNTAX.&Type
627  * }
628  * @param tvb the tv buffer of the current data
629  * @param pinfo the packet info of the current data
630  * @param tree the tree to append this item to
631  * @param offset the offset in the tvb
632  * @return modified offset
633  */
634 static guint
635 fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
636
637 /**
638  * CreateObject-Request ::= SEQUENCE {
639  *  objectSpecifier     [0] ObjectSpecifier,
640  *  listOfInitialValues [1] SEQUENCE OF BACnetPropertyValue OPTIONAL
641  * }
642  * @param tvb the tv buffer of the current data
643  * @param pinfo the packet info of the current data
644  * @param subtree the sub tree to append this item to
645  * @param offset the offset in the tvb
646  * @return modified offset
647  */
648 static guint
649 fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
650
651 /**
652  * CreateObject-Request ::= BACnetObjectIdentifier
653  * @param tvb the tv buffer of the current data
654  * @param pinfo the packet info of the current data
655  * @param tree the tree to append this item to
656  * @param offset the offset in the tvb
657  * @return modified offset
658  */
659 static guint
660 fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
661
662 /**
663  * DeleteObject-Request ::= SEQUENCE {
664  *  ObjectIdentifier    BACnetObjectIdentifer
665  * }
666  * @param tvb the tv buffer of the current data
667  * @param pinfo the packet info of the current data
668  * @param tree the tree to append this item to
669  * @param offset the offset in the tvb
670  * @return modified offset
671  */
672 static guint
673 fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
674
675 /**
676  * ReadProperty-Request ::= SEQUENCE {
677  *  objectIdentifier    [0] BACnetObjectIdentifier,
678  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
679  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
680  * }
681  * @param tvb the tv buffer of the current data
682  * @param pinfo the packet info of the current data
683  * @param tree the tree to append this item to
684  * @param offset the offset in the tvb
685  * @return modified offset
686  */
687 static guint
688 fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
689
690 /**
691  * ReadProperty-ACK ::= SEQUENCE {
692  *  objectIdentifier   [0] BACnetObjectIdentifier,
693  *  propertyIdentifier [1] BACnetPropertyIdentifier,
694  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
695  *  propertyValue      [3] ABSTRACT-SYNTAX.&Type
696  * }
697  * @param tvb the tv buffer of the current data
698  * @param pinfo the packet info of the current data
699  * @param tree the tree to append this item to
700  * @param offset the offset in the tvb
701  * @return modified offset
702  */
703 static guint
704 fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
705
706 /**
707  * ReadPropertyConditional-Request ::= SEQUENCE {
708  *  objectSelectionCriteria  [0] objectSelectionCriteria,
709  *  listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference OPTIONAL
710  * }
711  * @param tvb the tv buffer of the current data
712  * @param pinfo the packet info of the current data
713  * @param subtree the  sub tree to append this item to
714  * @param offset the offset in the tvb
715  * @return modified offset
716  */
717 static guint
718 fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
719
720 /**
721  * ReadPropertyConditional-ACK ::= SEQUENCE {
722  *  listOfPReadAccessResults    SEQUENCE OF ReadAccessResult OPTIONAL
723  * }
724  * @param tvb the tv buffer of the current data
725  * @param pinfo the packet info of the current data
726  * @param tree the tree to append this item to
727  * @param offset the offset in the tvb
728  * @return modified offset
729  */
730 static guint
731 fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
732
733 /**
734  * ReadPropertyMultiple-Request ::= SEQUENCE {
735  *  listOfReadAccessSpecs   SEQUENCE OF ReadAccessSpecification
736  * }
737  * @param tvb the tv buffer of the current data
738  * @param pinfo the packet info of the current data
739  * @param subtree the sub tree to append this item to
740  * @param offset the offset in the tvb
741  * @return offset modified
742  */
743 static guint
744 fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
745
746 /**
747  * ReadPropertyMultiple-Ack ::= SEQUENCE {
748  *  listOfReadAccessResults SEQUENCE OF ReadAccessResult
749  * }
750  * @param tvb the tv buffer of the current data
751  * @param pinfo the packet info of the current data
752  * @param tree the tree to append this item to
753  * @param offset the offset in the tvb
754  * @return offset modified
755  */
756 static guint
757 fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
758
759 /**
760  * ReadRange-Request ::= SEQUENCE {
761  *  objectIdentifier    [0] BACnetObjectIdentifier,
762  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
763  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
764  *  range   CHOICE {
765  *      byPosition  [3] SEQUENCE {
766  *          referencedIndex Unsigned,
767  *          count INTEGER
768  *          },
769  *      byTime      [4] SEQUENCE {
770  *          referenceTime BACnetDateTime,
771  *          count INTEGER
772  *          },
773  *      timeRange   [5] SEQUENCE {
774  *          beginningTime BACnetDateTime,
775  *          endingTime BACnetDateTime
776  *          },
777  *      } OPTIONAL
778  * }
779  * @param tvb the tv buffer of the current data
780  * @param pinfo the packet info of the current data
781  * @param tree the tree to append this item to
782  * @param offset the offset in the tvb
783  * @return modified offset
784  */
785 static guint
786 fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
787
788 /**
789  * ReadRange-ACK ::= SEQUENCE {
790  *  objectIdentifier   [0] BACnetObjectIdentifier,
791  *  propertyIdentifier [1] BACnetPropertyIdentifier,
792  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
793  *  resultFlags        [3] BACnetResultFlags,
794  *  itemCount          [4] Unsigned,
795  *  itemData           [5] SEQUENCE OF ABSTRACT-SYNTAX.&Type
796  * }
797  * @param tvb the tv buffer of the current data
798  * @param pinfo the packet info of the current data
799  * @param tree the tree to append this item to
800  * @param offset the offset in the tvb
801  * @return modified offset
802  */
803 static guint
804 fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
805
806 /**
807  * RemoveListElement-Request ::= SEQUENCE {
808  *  objectIdentifier    [0] BACnetObjectIdentifier,
809  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
810  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
811  *  listOfElements  [3] ABSTRACT-SYNTAX.&Type
812  * }
813  * @param tvb the tv buffer of the current data
814  * @param pinfo the packet info of the current data
815  * @param tree the tree to append this item to
816  * @param offset the offset in the tvb
817  * @return modified offset
818  */
819 static guint
820 fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
821
822 /**
823  * WriteProperty-Request ::= SEQUENCE {
824  *  objectIdentifier   [0] BACnetObjectIdentifier,
825  *  propertyIdentifier [1] BACnetPropertyIdentifier,
826  *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
827  *  propertyValue      [3] ABSTRACT-SYNTAX.&Type
828  *  priority           [4] Unsigned8 (1..16) OPTIONAL --used only when property is commandable
829  * }
830  * @param tvb the tv buffer of the current data
831  * @param pinfo the packet info of the current data
832  * @param tree the tree to append this item to
833  * @param offset the offset in the tvb
834  * @return modified offset
835  */
836 static guint
837 fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
838
839 /**
840  * WritePropertyMultiple-Request ::= SEQUENCE {
841  *  listOfWriteAccessSpecifications SEQUENCE OF WriteAccessSpecification
842  * }
843  * @param tvb the tv buffer of the current data
844  * @param pinfo the packet info of the current data
845  * @param tree the tree to append this item to
846  * @param offset the offset in the tvb
847  * @return modified offset
848  */
849 static guint
850 fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
851
852 /**
853  * DeviceCommunicationControl-Request ::= SEQUENCE {
854  *  timeDuration    [0] Unsigned16 OPTIONAL,
855  *  enable-disable  [1] ENUMERATED {
856  *      enable  (0),
857  *      disable (1)
858  *      },
859  *  password        [2] CharacterString (SIZE(1..20)) OPTIONAL
860  * }
861  * @param tvb the tv buffer of the current data
862  * @param pinfo the packet info of the current data
863  * @param tree the tree to append this item to
864  * @param offset the offset in the tvb
865  * @return modified offset
866  */
867 static guint
868 fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
869
870 /**
871  * ConfirmedPrivateTransfer-Request ::= SEQUENCE {
872  *  vendorID          [0] Unsigned,
873  *  serviceNumber     [1] Unsigned,
874  *  serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
875  * }
876  * @param tvb the tv buffer of the current data
877  * @param pinfo the packet info of the current data
878  * @param tree the tree to append this item to
879  * @param offset the offset in the tvb
880  * @return modified offset
881  */
882 static guint
883 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
884
885 /**
886  * ConfirmedPrivateTransfer-ACK ::= SEQUENCE {
887  *  vendorID      [0] Unsigned,
888  *  serviceNumber [1] Unsigned,
889  *  resultBlock   [2] ABSTRACT-SYNTAX.&Type OPTIONAL
890  * }
891  * @param tvb the tv buffer of the current data
892  * @param pinfo the packet info of the current data
893  * @param tree the tree to append this item to
894  * @param offset the offset in the tvb
895  * @return modified offset
896  */
897 static guint
898 fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
899
900 /**
901  * ConfirmedTextMessage-Request ::=  SEQUENCE {
902  *  textMessageSourceDevice [0] BACnetObjectIdentifier,
903  *  messageClass            [1] CHOICE {
904  *      numeric   [0] Unsigned,
905  *      character [1] CharacterString
906  *      } OPTIONAL,
907  *  messagePriority         [2] ENUMERATED {
908  *      normal (0),
909  *      urgent (1)
910  *      },
911  *  message [3] CharacterString
912  * }
913  * @param tvb the tv buffer of the current data
914  * @param pinfo the packet info of the current data
915  * @param tree the tree to append this item to
916  * @param offset the offset in the tvb
917  * @return modified offset
918  */
919 static guint
920 fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
921
922 /**
923  * ReinitializeDevice-Request ::= SEQUENCE {
924  *  reinitializedStateOfDevice  [0] ENUMERATED {
925  *      coldstart    (0),
926  *      warmstart    (1),
927  *      startbackup  (2),
928  *      endbackup    (3),
929  *      startrestore (4),
930  *      endrestore   (5),
931  *      abortrestor  (6)
932  *      },
933  *  password                    [1] CharacterString (SIZE(1..20)) OPTIONAL
934  * }
935  * @param tvb the tv buffer of the current data
936  * @param pinfo the packet info of the current data
937  * @param tree the tree to append this item to
938  * @param offset the offset in the tvb
939  * @return modified offset
940  */
941 static guint
942 fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
943
944 /**
945  * VTOpen-Request ::= SEQUENCE {
946  *  vtClass BACnetVTClass,
947  *  localVTSessionIdentifier    Unsigned8
948  * }
949  * @param tvb the tv buffer of the current data
950  * @param pinfo the packet info of the current data
951  * @param tree the tree to append this item to
952  * @param offset the offset in the tvb
953  * @return modified offset
954  */
955 static guint
956 fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
957
958 /**
959  * VTOpen-ACK ::= SEQUENCE {
960  *  remoteVTSessionIdentifier   Unsigned8
961  * }
962  * @param tvb the tv buffer of the current data
963  * @param pinfo the packet info of the current data
964  * @param tree the tree to append this item to
965  * @param offset the offset in the tvb
966  * @return modified offset
967  */
968 static guint
969 fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
970
971 /**
972  * VTClose-Request ::= SEQUENCE {
973  *  listOfRemoteVTSessionIdentifiers    SEQUENCE OF Unsigned8
974  * }
975  * @param tvb the tv buffer of the current data
976  * @param pinfo the packet info of the current data
977  * @param tree the tree to append this item to
978  * @param offset the offset in the tvb
979  * @return modified offset
980  */
981 static guint
982 fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
983
984 /**
985  * VTData-Request ::= SEQUENCE {
986  *  vtSessionIdentifier Unsigned8,
987  *  vtNewData           OCTET STRING,
988  *  vtDataFlag          Unsigned (0..1)
989  * }
990  * @param tvb the tv buffer of the current data
991  * @param pinfo the packet info of the current data
992  * @param tree the tree to append this item to
993  * @param offset the offset in the tvb
994  * @return modified offset
995  */
996 static guint
997 fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
998
999 /**
1000  * VTData-ACK ::= SEQUENCE {
1001  *  allNewDataAccepted  [0] BOOLEAN,
1002  *  acceptedOctetCount  [1] Unsigned OPTIONAL -- present only if allNewDataAccepted = FALSE
1003  * }
1004  * @param tvb the tv buffer of the current data
1005  * @param pinfo the packet info of the current data
1006  * @param tree the tree to append this item to
1007  * @param offset the offset in the tvb
1008  * @return modified offset
1009  */
1010 static guint
1011 fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1012
1013 /**
1014  * Authenticate-Request ::= SEQUENCE {
1015  *  pseudoRandomNumber     [0] Unsigned32,
1016  *  excpectedInvokeID      [1] Unsigned8 OPTIONAL,
1017  *  operatorName           [2] CharacterString OPTIONAL,
1018  *  operatorPassword       [3] CharacterString (SIZE(1..20)) OPTIONAL,
1019  *  startEncypheredSession [4] BOOLEAN OPTIONAL
1020  * }
1021  * @param tvb the tv buffer of the current data
1022  * @param pinfo the packet info of the current data
1023  * @param tree the tree to append this item to
1024  * @param offset the offset in the tvb
1025  * @return modified offset
1026  */
1027 static guint
1028 fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1029
1030 /**
1031  * Authenticate-ACK ::= SEQUENCE {
1032  *  modifiedRandomNumber    Unsigned32,
1033  * }
1034  * @param tvb the tv buffer of the current data
1035  * @param pinfo the packet info of the current data
1036  * @param tree the tree to append this item to
1037  * @param offset the offset in the tvb
1038  * @return modified offset
1039  */
1040 static guint
1041 fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1042
1043 /**
1044  * RequestKey-Request ::= SEQUENCE {
1045  *  requestingDeviceIdentifier BACnetObjectIdentifier,
1046  *  requestingDeviceAddress    BACnetAddress,
1047  *  remoteDeviceIdentifier     BACnetObjectIdentifier,
1048  *  remoteDeviceAddress        BACnetAddress
1049  * }
1050  * @param tvb the tv buffer of the current data
1051  * @param pinfo the packet info of the current data
1052  * @param tree the tree to append this item to
1053  * @param offset the offset in the tvb
1054  * @return modified offset
1055  */
1056 static guint
1057 fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1058
1059 /**
1060  * Unconfirmed-Service-Request ::= CHOICE {
1061  * }
1062  * @param tvb the tv buffer of the current data
1063  * @param pinfo the packet info of the current data
1064  * @param tree the tree to append this item to
1065  * @param offset the offset in the tvb
1066  * @param service_choice the service choice
1067  * @return modified offset
1068  */
1069 static guint
1070 fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
1071
1072 /**
1073  * UnconfirmedCOVNotification-Request ::= SEQUENCE {
1074  *  subscriberProcessIdentifier [0] Unsigned32,
1075  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
1076  *  monitoredObjectIdentifier   [2] BACnetObjectIdentifer,
1077  *  timeRemaining               [3] unsigned,
1078  *  listOfValues                [4] SEQUENCE OF BACnetPropertyValues
1079  * }
1080  * @param tvb the tv buffer of the current data
1081  * @param pinfo the packet info of the current data
1082  * @param tree the tree to append this item to
1083  * @param offset the offset in the tvb
1084  * @return modified offset
1085  */
1086 static guint
1087 fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1088
1089 /**
1090  * UnconfirmedEventNotification-Request ::= SEQUENCE {
1091  *  ProcessIdentifier           [0] Unsigned32,
1092  *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifer,
1093  *  eventObjectIdentifier       [2] BACnetObjectIdentifer,
1094  *  timeStamp                   [3] BACnetTimeStamp,
1095  *  notificationClass           [4] unsigned,
1096  *  priority                    [5] unsigned8,
1097  *  eventType                   [6] BACnetEventType,
1098  *  messageText                 [7] CharacterString OPTIONAL,
1099  *  notifyType                  [8] BACnetNotifyType,
1100  *  ackRequired                 [9] BOOLEAN OPTIONAL,
1101  *  fromState                  [10] BACnetEventState OPTIONAL,
1102  *  toState                    [11] BACnetEventState,
1103  *  eventValues                [12] BACnetNotificationParameters OPTIONAL
1104  * }
1105  * @param tvb the tv buffer of the current data
1106  * @param pinfo the packet info of the current data
1107  * @param tree the tree to append this item to
1108  * @param offset the offset in the tvb
1109  * @return modified offset
1110  */
1111 static guint
1112 fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1113
1114 /**
1115  * I-Am-Request ::= SEQUENCE {
1116  *  aAmDeviceIdentifier BACnetObjectIdentifier,
1117  *  maxAPDULengthAccepted   Unsigned,
1118  *  segmentationSupported   BACnetSegmentation,
1119  *  vendorID    Unsigned
1120  * }
1121  * @param tvb the tv buffer of the current data
1122  * @param pinfo the packet info of the current data
1123  * @param tree the tree to append this item to
1124  * @param offset the offset in the tvb
1125  * @return modified offset
1126  */
1127 static guint
1128 fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1129
1130
1131 /**
1132  * I-Have-Request ::= SEQUENCE {
1133  *  deviceIdentifier  BACnetObjectIdentifier,
1134  *  objectIdentifier  BACnetObjectIdentifier,
1135  *  objectName        CharacterString
1136  * }
1137  * @param tvb the tv buffer of the current data
1138  * @param pinfo the packet info of the current data
1139  * @param tree the tree to append this item to
1140  * @param offset the offset in the tvb
1141  * @return modified offset
1142  */
1143 static guint
1144 fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1145
1146 /**
1147  * UnconfirmedPrivateTransfer-Request ::= SEQUENCE {
1148  *  vendorID          [0] Unsigned,
1149  *  serviceNumber     [1] Unsigned,
1150  *  serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
1151  * }
1152  * @param tvb the tv buffer of the current data
1153  * @param pinfo the packet info of the current data
1154  * @param tree the tree to append this item to
1155  * @param offset the offset in the tvb
1156  * @return modified offset
1157  */
1158 static guint
1159 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1160
1161 /**
1162  * UnconfirmedTextMessage-Request ::=  SEQUENCE {
1163  *  textMessageSourceDevice [0] BACnetObjectIdentifier,
1164  *  messageClass            [1] CHOICE {
1165  *      numeric   [0] Unsigned,
1166  *      character [1] CharacterString
1167  *      } OPTIONAL,
1168  *  messagePriority         [2] ENUMERATED {
1169  *      normal (0),
1170  *      urgent (1)
1171  *      },
1172  *  message                 [3] CharacterString
1173  * }
1174  * @param tvb the tv buffer of the current data
1175  * @param pinfo the packet info of the current data
1176  * @param tree the tree to append this item to
1177  * @param offset the offset in the tvb
1178  * @return modified offset
1179  */
1180 static guint
1181 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1182
1183 /**
1184  * TimeSynchronization-Request ::=  SEQUENCE {
1185  *  BACnetDateTime
1186  * }
1187  * @param tvb the tv buffer of the current data
1188  * @param pinfo the packet info of the current data
1189  * @param tree the tree to append this item to
1190  * @param offset the offset in the tvb
1191  * @return modified offset
1192  */
1193 static guint
1194 fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1195
1196 /**
1197  * UTCTimeSynchronization-Request ::=  SEQUENCE {
1198  *  BACnetDateTime
1199  * }
1200  * @param tvb the tv buffer of the current data
1201  * @param pinfo the packet info of the current data
1202  * @param tree the tree to append this item to
1203  * @param offset the offset in the tvb
1204  * @return modified offset
1205  */
1206 static guint
1207 fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1208
1209 /**
1210  * Who-Has-Request ::=  SEQUENCE {
1211  *  limits SEQUENCE {
1212  *      deviceInstanceRangeLowLimit  [0] Unsigned (0..4194303),
1213  *      deviceInstanceRangeHighLimit [1] Unsigned (0..4194303)
1214  *      } OPTIONAL,
1215  *  object CHOICE {
1216  *      objectIdentifier             [2] BACnetObjectIdentifier,
1217  *      objectName                   [3] CharacterString
1218  *      }
1219  * }
1220  * @param tvb the tv buffer of the current data
1221  * @param pinfo the packet info of the current data
1222  * @param tree the tree to append this item to
1223  * @param offset the offset in the tvb
1224  * @return modified offset
1225  */
1226 static guint
1227 fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1228
1229 /**
1230  * Who-Is-Request ::= SEQUENCE {
1231  *  deviceInstanceRangeLowLimit  [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1232  *  deviceInstanceRangeHighLimit [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1233  * }
1234  * @param tvb the tv buffer of the current data
1235  * @param tree the tree to append this item to
1236  * @param offset the offset in the tvb
1237  * @return modified offset
1238  */
1239 static guint
1240 fWhoIsRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1241
1242 /**
1243  * BACnet-Error ::= CHOICE {
1244  *  addListElement           [8] ChangeList-Error,
1245  *  removeListElement        [9] ChangeList-Error,
1246  *  writePropertyMultiple   [16] WritePropertyMultiple-Error,
1247  *  confirmedPrivatTransfer [18] ConfirmedPrivateTransfer-Error,
1248  *  vtClose                 [22] VTClose-Error,
1249  *  readRange               [26] ObjectAccessService-Error
1250  *                          [default] Error
1251  * }
1252  * @param tvb the tv buffer of the current data
1253  * @param pinfo the packet info of the current data
1254  * @param tree the tree to append this item to
1255  * @param offset the offset in the tvb
1256  * @param service the service
1257  * @return modified offset
1258  */
1259 static guint
1260 fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service);
1261
1262 /**
1263  * Dissect a BACnetError in a context tag
1264  *
1265  * @param tvb the tv buffer of the current data
1266  * @param pinfo the packet info of the current data
1267  * @param tree the tree to append this item to
1268  * @param offset the offset in the tvb
1269  * @return modified offset
1270  */
1271 static guint fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1272
1273 /**
1274  * ChangeList-Error ::= SEQUENCE {
1275  *    errorType                [0] Error,
1276  *    firstFailedElementNumber [1] Unsigned
1277  *    }
1278  * }
1279  * @param tvb the tv buffer of the current data
1280  * @param pinfo the packet info of the current data
1281  * @param tree the tree to append this item to
1282  * @param offset the offset in the tvb
1283  * @return modified offset
1284  */
1285 static guint
1286 fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1287
1288 /**
1289  * CreateObject-Error ::= SEQUENCE {
1290  *    errorType                [0] Error,
1291  *    firstFailedElementNumber [1] Unsigned
1292  *    }
1293  * }
1294  * @param tvb the tv buffer of the current data
1295  * @param pinfo the packet info of the current data
1296  * @param tree the tree to append this item to
1297  * @param offset the offset in the tvb
1298  * @return modified offset
1299  */
1300 static guint
1301 fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1302
1303 /**
1304  * ConfirmedPrivateTransfer-Error ::= SEQUENCE {
1305  *    errorType       [0] Error,
1306  *    vendorID        [1] Unsigned,
1307  *    serviceNumber   [2] Unsigned,
1308  *    errorParameters [3] ABSTRACT-SYNTAX.&Type OPTIONAL
1309  *    }
1310  * }
1311  * @param tvb the tv buffer of the current data
1312  * @param pinfo the packet info of the current data
1313  * @param tree the tree to append this item to
1314  * @param offset the offset in the tvb
1315  * @return modified offset
1316  */
1317 static guint
1318 fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1319
1320 /**
1321  * WritePropertyMultiple-Error ::= SEQUENCE {
1322  *    errorType               [0] Error,
1323  *    firstFailedWriteAttempt [1] Unsigned
1324  *    }
1325  * }
1326  * @param tvb the tv buffer of the current data
1327  * @param pinfo the packet info of the current data
1328  * @param tree the tree to append this item to
1329  * @param offset the offset in the tvb
1330  * @return modified offset
1331  */
1332 static guint
1333 fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1334
1335 /**
1336  * VTClose-Error ::= SEQUENCE {
1337  *    errorType                  [0] Error,
1338  *    listOfVTSessionIdentifiers [1] SEQUENCE OF Unsigned8 OPTIONAL
1339  *    }
1340  * }
1341  * @param tvb the tv buffer of the current data
1342  * @param pinfo the packet info of the current data
1343  * @param tree the tree to append this item to
1344  * @param offset the offset in the tvb
1345  * @return modified offset
1346  */
1347 static guint
1348 fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1349
1350 /**
1351  * BACnet Application Types chapter 20.2.1
1352  * @param tvb the tv buffer of the current data
1353  * @param pinfo the packet info of the current data
1354  * @param tree the tree to append this item to
1355  * @param offset the offset in the tvb
1356  * @param label the label of this item
1357  * @return modified offset
1358  */
1359 static guint
1360 fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
1361
1362 /**
1363  * BACnetActionCommand ::= SEQUENCE {
1364  *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1365  *  objectIdentifier    [1] BACnetObjectIdentifier,
1366  *  propertyIdentifier  [2] BACnetPropertyIdentifier,
1367  *  propertyArrayIndex  [3] Unsigned OPTIONAL, -- used only with array datatype
1368  *  propertyValue       [4] ABSTRACT-SYNTAX.&Type,
1369  *  priority            [5] Unsigned (1..16) OPTIONAL, -- used only when property is commandable
1370  *  postDelay           [6] Unsigned OPTIONAL,
1371  *  quitOnFailure       [7] BOOLEAN,
1372  *  writeSuccessful     [8] BOOLEAN
1373  * }
1374  * @param tvb the tv buffer of the current data
1375  * @param pinfo the packet info of the current data
1376  * @param tree the tree to append this item to
1377  * @param offset the offset in the tvb
1378  * @param tag_match the tag number
1379  * @return modified offset
1380  */
1381 static guint
1382 fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match);
1383
1384 /**
1385  * BACnetActionList ::= SEQUENCE {
1386  *  action  [0] SEQUENCE of BACnetActionCommand
1387  * }
1388  * @param tvb the tv buffer of the current data
1389  * @param pinfo the packet info of the current data
1390  * @param tree the tree to append this item to
1391  * @param offset the offset in the tvb
1392  * @return modified offset
1393  */
1394 static guint
1395 fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1396
1397 /** BACnetAddress ::= SEQUENCE {
1398  *  network-number  Unsigned16, -- A value 0 indicates the local network
1399  *  mac-address     OCTET STRING -- A string of length 0 indicates a broadcast
1400  * }
1401  * @param tvb the tv buffer of the current data
1402  * @param pinfo the packet info of the current data
1403  * @param tree the tree to append this item to
1404  * @param offset the offset in the tvb
1405  * @return modified offset
1406  */
1407 static guint
1408 fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1409
1410 /**
1411  * BACnetAddressBinding ::= SEQUENCE {
1412  *  deviceObjectID  BACnetObjectIdentifier
1413  *  deviceAddress   BacnetAddress
1414  * }
1415  * @param tvb the tv buffer of the current data
1416  * @param pinfo the packet info of the current data
1417  * @param tree the tree to append this item to
1418  * @param offset the offset in the tvb
1419  * @return modified offset
1420  */
1421 static guint
1422 fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1423
1424 /**
1425  * BACnetCalendarEntry ::= CHOICE {
1426  *  date        [0] Date,
1427  *  dateRange   [1] BACnetDateRange,
1428  *  weekNDay    [2] BacnetWeekNday
1429  * }
1430  * @param tvb the tv buffer of the current data
1431  * @param pinfo the packet info of the current data
1432  * @param tree the tree to append this item to
1433  * @param offset the offset in the tvb
1434  * @return modified offset
1435  */
1436 static guint
1437 fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1438
1439 /**
1440  * BACnetClientCOV ::= CHOICE {
1441  *  real-increment  REAL,
1442  *  default-increment   NULL
1443  * }
1444  * @param tvb the tv buffer of the current data
1445  * @param tree the tree to append this item to
1446  * @param offset the offset in the tvb
1447  * @return modified offset
1448  */
1449 static guint
1450 fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1451
1452
1453 /**
1454  * BACnetDailySchedule ::= SEQUENCE {
1455  *  day-schedule    [0] SENQUENCE OF BACnetTimeValue
1456  * }
1457  * @param tvb the tv buffer of the current data
1458  * @param pinfo the packet info of the current data
1459  * @param tree the tree to append this item to
1460  * @param offset the offset in the tvb
1461  * @return modified offset
1462  */
1463 static guint
1464 fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1465
1466 /**
1467  * BACnetWeeklySchedule ::= SEQUENCE {
1468  *  week-schedule    SENQUENCE SIZE (7) OF BACnetDailySchedule
1469  * }
1470  * @param tvb the tv buffer of the current data
1471  * @param pinfo the packet info of the current data
1472  * @param tree the tree to append this item to
1473  * @param offset the offset in the tvb
1474  * @return modified offset
1475  */
1476 static guint
1477 fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1478
1479 /**
1480  * BACnetDateRange ::= SEQUENCE {
1481  *  StartDate   Date,
1482  *  EndDate     Date
1483  * }
1484  * @param tvb the tv buffer of the current data
1485  * @param pinfo the packet info of the current data
1486  * @param tree the tree to append this item to
1487  * @param offset the offset in the tvb
1488  * @return modified offset
1489  */
1490 static guint
1491 fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1492
1493 /**
1494  * BACnetDateTime ::= SEQUENCE {
1495  *  date   Date,
1496  *  time   Time
1497  * }
1498  * @param tvb the tv buffer of the current data
1499  * @param pinfo the packet info of the current data
1500  * @param tree the tree to append this item to
1501  * @param offset the offset in the tvb
1502  * @param label the label of this item
1503  * @return modified offset
1504  */
1505 static guint
1506 fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
1507
1508 /**
1509  * BACnetDestination ::= SEQUENCE {
1510  *  validDays   BACnetDaysOfWeek,
1511  *  fromTime    Time,
1512  *  toTime      Time,
1513  *  recipient   BACnetRecipient,
1514  *  processIdentifier   Unsigned32,
1515  *  issueConfirmedNotifications BOOLEAN,
1516  *  transitions BACnetEventTransitionBits
1517  * }
1518  * @param tvb the tv buffer of the current data
1519  * @param pinfo the packet info of the current data
1520  * @param tree the tree to append this item to
1521  * @param offset the offset in the tvb
1522  * @return modified offset
1523  */
1524 static guint
1525 fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1526
1527 /**
1528  * BACnetDeviceObjectPropertyReference ::= SEQUENCE {
1529  *  objectIdentifier    [0] BACnetObjectIdentifier,
1530  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1531  *  propertyArrayIndex  [2] Unsigend OPTIONAL,
1532  *  deviceIdentifier    [3] BACnetObjectIdentifier OPTIONAL
1533  * }
1534  * @param tvb the tv buffer of the current data
1535  * @param pinfo the packet info of the current data
1536  * @param tree the tree to append this item to
1537  * @param offset the offset in the tvb
1538  * @return modified offset
1539  */
1540 static guint
1541 fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1542
1543 /**
1544  * BACnetObjectPropertyReference ::= SEQUENCE {
1545  *  objectIdentifier    [0] BACnetObjectIdentifier,
1546  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1547  *  propertyArrayIndex  [2] Unsigend OPTIONAL,
1548  * }
1549  * @param tvb the tv buffer of the current data
1550  * @param pinfo the packet info of the current data
1551  * @param tree the tree to append this item to
1552  * @param offset the offset in the tvb
1553  * @return modified offset
1554  */
1555 static guint
1556 fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1557
1558 /**
1559  * BACnetDeviceObjectReference ::= SEQUENCE {
1560  *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1561  *  objectIdentifier    [1] BACnetObjectIdentifier
1562  * }
1563  * @param tvb the tv buffer of the current data
1564  * @param pinfo the packet info of the current data
1565  * @param tree the tree to append this item to
1566  * @param offset the offset in the tvb
1567  * @return modified offset
1568  */
1569 static guint
1570 fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1571
1572 /**
1573  * BACnetEventParameter ::= CHOICE {
1574  *  change-of-bitstring             [0] SEQUENCE {
1575  *      time-delay                       [0] Unsigned,
1576  *      bitmask                          [1] BIT STRING,
1577  *      list-of-bitstring-values         [2] SEQUENCE OF BIT STRING
1578  *      },
1579  *  change-of-state                 [1] SEQUENCE {
1580  *      time-delay     [0] Unsigned,
1581  *      list-of-values [1] SEQUENCE OF BACnetPropertyStates
1582  *      },
1583  *  change-of-value                 [2] SEQUENCE {
1584  *      time-delay   [0] Unsigned,
1585  *      cov-criteria [1] CHOICE {
1586  *          bitmask                       [0] BIT STRING,
1587  *          referenced-property-increment [1] REAL
1588  *          }
1589  *      },
1590  *  command-failure                 [3] SEQUENCE {
1591  *      time-delay                       [0] Unsigned,
1592  *      feedback-property-reference      [1] BACnetDeviceObjectPropertyReference
1593  *      },
1594  *  floating-limit                  [4] SEQUENCE {
1595  *      time-delay                       [0] Unsigned,
1596  *      setpoint-reference               [1] BACnetDeviceObjectPropertyReference,
1597  *      low-diff-limit                   [2] REAL,
1598  *      high-diff-limit                  [3] REAL,
1599  *      deadband                         [4] REAL
1600  *      },
1601  *  out-of-range                    [5] SEQUENCE {
1602  *      time-delay                       [0] Unsigned,
1603  *      low-limit                        [1] REAL,
1604  *      high-limit                       [2] REAL,
1605  *      deadband                         [3] REAL
1606  *      },
1607  *  -- context tag 7 is deprecated
1608  *  change-of-life-safety           [8] SEQUENCE {
1609  *      time-delay                       [0] Unsigned,
1610  *      list-of-life-safety-alarm-values [1] SEQUENCE OF BACnetLifeSafetyState,
1611  *      list-of-alarm-values             [2] SEQUENCE OF BACnetLifeSafetyState,
1612  *      mode-property-reference          [3] BACnetDeviceObjectPropertyReference
1613  *      },
1614  *  extended                        [9] SEQUENCE {
1615  *      vendor-id                        [0] Unsigned16,
1616  *      extended-event-type              [1] Unsigned,
1617  *      parameters                       [2] SEQUENCE OF CHOICE {
1618  *          null        NULL,
1619  *          real        REAL,
1620  *          integer     Unsigned,
1621  *          boolean     BOOLEAN,
1622  *          double      Double,
1623  *          octet       OCTET STRING,
1624  *          bitstring   BIT STRING,
1625  *          enum        ENUMERATED,
1626  *          reference   [0] BACnetDeviceObjectPropertyReference
1627  *          }
1628  *      },
1629  *  buffer-ready                    [10] SEQUENCE {
1630  *      notification-threshold           [0] Unsigned,
1631  *      previous-notification-count      [1] Unsigned32
1632  *      },
1633  * unsigned-range                   [11] SEQUENCE {
1634  *      time-delay                       [0] Unsigned,
1635  *      low-limit                        [1] Unsigned,
1636  *      high-limit                       [2] Unsigned,
1637  *      }
1638  * -- context tag 12 is reserved for future addenda
1639  * access-event                     [13] SEQUENCE {
1640  *      list-of-access-events            [0] SEQUENCE OF BACnetAccessEvent,
1641  *      access-event-time-reference      [1] BACnetDeviceObjectPropertyReference
1642  *      }
1643  * double-out-of-range              [14] SEQUENCE {
1644  *      time-delay                       [0] Unsigned,
1645  *      low-limit                        [1] Double,
1646  *      high-limit                       [2] Double,
1647  *      deadband                         [3] Double
1648  *  }
1649  *  signed-out-of-range             [15] SEQUENCE {
1650  *      time-delay                       [0] Unsigned,
1651  *      low-limit                        [1] INTEGER,
1652  *      high-limit                       [2] INTEGER,
1653  *      deadband                         [3] Unsigned
1654  *  }
1655  *  unsigned-out-of-range           [16] SEQUENCE {
1656  *      time-delay                       [0] Unsigned,
1657  *      low-limit                        [1] Unsigned,
1658  *      high-limit                       [2] Unsigned,
1659  *      deadband                         [3] Unsigned
1660  *   }
1661  *  change-of-characterstring       [17] SEQUENCE {
1662  *      time-delay                       [0] Unsigned,
1663  *      list-of-alarm-values             [1] SEQUENCE OF CharacterString,
1664  *   }
1665  *  change-of-status-flags          [18] SEQUENCE {
1666  *      time-delay                       [0] Unsigned,
1667  *      selected-flags                   [1] BACnetStatusFlags
1668  *   }
1669  * }
1670  * @param tvb the tv buffer of the current data
1671  * @param tree the tree to append this item to
1672  * @param offset the offset in the tvb
1673  * @return modified offset
1674  */
1675 static guint
1676 fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1677
1678
1679
1680 /**
1681  * BACnetLogRecord ::= SEQUENCE {
1682  *  timestamp   [0] BACnetDateTime,
1683  *  logDatum    [1] CHOICE {
1684  *      log-status      [0] BACnetLogStatus,
1685  *      boolean-value   [1] BOOLEAN,
1686  *      real-value      [2] REAL,
1687  *      enum-value      [3] ENUMERATED, -- Optionally limited to 32 bits
1688  *      unsigned-value  [4] Unsigned, -- Optionally limited to 32 bits
1689  *      signed-value    [5] INTEGER, -- Optionally limited to 32 bits
1690  *      bitstring-value [6] BIT STRING, -- Optionally limited to 32 bits
1691  *      null-value      [7] NULL,
1692  *      failure         [8] Error,
1693  *      time-change     [9] REAL,
1694  *      any-value       [10] ABSTRACT-SYNTAX.&Type -- Optional
1695  *      }
1696  *  statusFlags [2] BACnetStatusFlags OPTIONAL
1697  * }
1698  * @param tvb the tv buffer of the current data
1699  * @param pinfo the packet info of the current data
1700  * @param tree the tree to append this item to
1701  * @param offset the offset in the tvb
1702  * @return modified offset
1703  */
1704 static guint
1705 fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1706
1707 /**
1708  * BACnetEventLogRecord ::= SEQUENCE {
1709  *  timestamp [0] BACnetDateTime,
1710  *  logDatum  [1] CHOICE {
1711  *      log-status   [0] BACnetLogStatus,
1712  *      notification [1] ConfirmedEventNotification-Request,
1713  *      time-change  [2] REAL,
1714  *      }
1715  * }
1716  * @param tvb the tv buffer of the current data
1717  * @param pinfo the packet info of the current data
1718  * @param tree the tree to append this item to
1719  * @param offset the offset in the tvb
1720  * @return modified offset
1721  */
1722 static guint
1723 fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1724
1725 static guint
1726 fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1727
1728 /**
1729  * BACnetNotificationParameters ::= CHOICE {
1730  *  change-of-bitstring [0] SEQUENCE {
1731  *      referenced-bitstring [0] BIT STRING,
1732  *      status-flags         [1] BACnetStatusFlags
1733  *      },
1734  *  change-of-state [1] SEQUENCE {
1735  *      new-state            [0] BACnetPropertyStatus,
1736  *      status-flags         [1] BACnetStatusFlags
1737  *      },
1738  *  change-of-value [2] SEQUENCE {
1739  *      new-value            [0] CHOICE {
1740  *          changed-bits        [0] BIT STRING,
1741  *          changed-value       [1] REAL
1742  *          },
1743  *      status-flags         [1] BACnetStatusFlags
1744  *      },
1745  *  command-failure [3] SEQUENCE {
1746  *      command-value        [0] ABSTRACT-SYNTAX.&Type, -- depends on ref property
1747  *      status-flags         [1] BACnetStatusFlags
1748  *      feedback-value       [2] ABSTRACT-SYNTAX.&Type -- depends on ref property
1749  *      },
1750  *  floating-limit [4]  SEQUENCE {
1751  *      reference-value      [0] REAL,
1752  *      status-flags         [1] BACnetStatusFlags
1753  *      setpoint-value       [2] REAL,
1754  *      error-limit          [3] REAL
1755  *      },
1756  *  out-of-range [5]    SEQUENCE {
1757  *      exceeding-value      [0] REAL,
1758  *      status-flags         [1] BACnetStatusFlags
1759  *      deadband             [2] REAL,
1760  *      exceeded-limit       [3] REAL
1761  *      },
1762  *  complex-event-type  [6] SEQUENCE OF BACnetPropertyValue,
1763  * -- complex tag 7 is deprecated
1764  *  change-of-life-safety [8]   SEQUENCE {
1765  *      new-state            [0] BACnetLifeSafetyState,
1766  *      new-mode             [1] BACnetLifeSafetyState
1767  *      status-flags         [2] BACnetStatusFlags,
1768  *      operation-expected   [3] BACnetLifeSafetyOperation
1769  *      },
1770  *  extended [9]   SEQUENCE {
1771  *      vendor-id            [0] Unsigned16,
1772  *      extended-event-type  [1] Unsigned,
1773  *      parameters           [2] SEQUENCE OF CHOICE {
1774  *          null                NULL,
1775  *          real                REAL,
1776  *          integer             Unsigned,
1777  *          boolean             BOOLEAN,
1778  *          double              Double,
1779  *          octet               OCTET STRING,
1780  *          bitstring           BIT STRING,
1781  *          enum                ENUMERATED,
1782  *          propertyValue       [0] BACnetDeviceObjectPropertyValue
1783  *          }
1784  *      },
1785  *  buffer-ready [10]    SEQUENCE {
1786  *      buffer-property      [0] BACnetDeviceObjectPropertyReference,
1787  *      previous-notification[1] Unsigned32,
1788  *      current-notification [2] BACneUnsigned32tDateTime
1789  *      },
1790  *  unsigned-range [11]    SEQUENCE {
1791  *      exceeding-value      [0] Unsigned,
1792  *      status-flags         [1] BACnetStatusFlags,
1793  *      exceeded-limit       [2] Unsigned
1794  *      },
1795  * -- context tag 12 is reserved for future addenda
1796  *  access-event [13]    SEQUENCE {
1797  *      access-event          [0] BACnetAccessEvent,
1798  *      status-flags          [1] BACnetStatusFlags,
1799  *      access-event-tag      [2] Unsigned,
1800  *      access-event-time     [3] BACnetTimeStamp,
1801  *      access-credential     [4] BACnetDeviceObjectReference,
1802  *      authentication-factor [5] BACnetAuthenticationFactor OPTIONAL
1803  *      },
1804  *  double-out-of-range [14]    SEQUENCE {
1805  *      exceeding-value      [0] Double,
1806  *      status-flags         [1] BACnetStatusFlags
1807  *      deadband             [2] Double,
1808  *      exceeded-limit       [3] Double
1809  *      },
1810  *  signed-out-of-range [15]    SEQUENCE {
1811  *      exceeding-value      [0] INTEGER,
1812  *      status-flags         [1] BACnetStatusFlags
1813  *      deadband             [2] Unsigned,
1814  *      exceeded-limit       [3] INTEGER
1815  *      },
1816  *  unsigned-out-of-range [16]    SEQUENCE {
1817  *      exceeding-value      [0] Unsigned,
1818  *      status-flags         [1] BACnetStatusFlags
1819  *      deadband             [2] Unsigned,
1820  *      exceeded-limit       [3] Unsigned
1821  *      },
1822  *  change-of-characterstring [17]    SEQUENCE {
1823  *      changed-value        [0] CharacterString,
1824  *      status-flags         [1] BACnetStatusFlags
1825  *      alarm-value          [2] CharacterString
1826  *      },
1827  *  change-of-status-flags [18]    SEQUENCE {
1828  *      present-value        [0] ABSTRACT-SYNTAX.&Type OPTIONAL,
1829  *                              -- depends on referenced property
1830  *      referenced-flags     [1] BACnetStatusFlags
1831  *      },
1832  * }
1833  * @param tvb the tv buffer of the current data
1834  * @param pinfo the packet info of the current data
1835  * @param tree the tree to append this item to
1836  * @param offset the offset in the tvb
1837  * @return modified offset
1838  */
1839 static guint
1840 fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1841
1842 /**
1843  * BACnetObjectPropertyReference ::= SEQUENCE {
1844  *  objectIdentifier    [0] BACnetObjectIdentifier,
1845  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1846  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
1847  * }
1848  * @param tvb the tv buffer of the current data
1849  * @param pinfo the packet info of the current data
1850  * @param tree the tree to append this item to
1851  * @param offset the offset in the tvb
1852  * @return modified offset
1853  */
1854 static guint
1855 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1856
1857 #if 0
1858 /**
1859  * BACnetObjectPropertyValue ::= SEQUENCE {
1860  *      objectIdentifier   [0] BACnetObjectIdentifier,
1861  *      propertyIdentifier [1] BACnetPropertyIdentifier,
1862  *      propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
1863  *                                                -- if omitted with an array the entire array is referenced
1864  *      value              [3] ABSTRACT-SYNTAX.&Type, --any datatype appropriate for the specified property
1865  *      priority           [4] Unsigned (1..16) OPTIONAL
1866  * }
1867  * @param tvb the tv buffer of the current data
1868  * @param tree the tree to append this item to
1869  * @param offset the offset in the tvb
1870  * @return modified offset
1871  */
1872 static guint
1873 fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, guint offset);
1874 #endif
1875
1876 /**
1877  * BACnetPriorityArray ::= SEQUENCE SIZE (16) OF BACnetPriorityValue
1878  * @param tvb the tv buffer of the current data
1879  * @param pinfo the packet info of the current data
1880  * @param tree the tree to append this item to
1881  * @param offset the offset in the tvb
1882  * @return modified offset
1883  */
1884 static guint
1885 fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1886
1887 static guint
1888 fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list);
1889
1890 /**
1891  * BACnetPropertyReference ::= SEQUENCE {
1892  *  propertyIdentifier  [0] BACnetPropertyIdentifier,
1893  *  propertyArrayIndex  [1] Unsigned OPTIONAL, -- used only with array datatype
1894  * }
1895  * @param tvb the tv buffer of the current data
1896  * @param pinfo the packet info of the current data
1897  * @param tree the tree to append this item to
1898  * @param offset the offset in the tvb
1899  * @return modified offset
1900  */
1901 static guint
1902 fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list);
1903
1904 /* static guint
1905 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset); */
1906
1907 static guint
1908 fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1909
1910 static guint
1911 fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1912
1913 /**
1914  * BACnetPropertyValue ::= SEQUENCE {
1915  *      PropertyIdentifier [0] BACnetPropertyIdentifier,
1916  *      propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatypes
1917  *                                                -- if omitted with an array the entire array is referenced
1918  *      value              [2] ABSTRACT-SYNTAX.&Type, -- any datatype appropriate for the specified property
1919  *      priority           [3] Unsigned (1..16) OPTIONAL -- used only when property is commandable
1920  * }
1921  * @param tvb the tv buffer of the current data
1922  * @param pinfo the packet info of the current data
1923  * @param tree the tree to append this item to
1924  * @param offset the offset in the tvb
1925  * @return modified offset
1926  */
1927 static guint
1928 fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1929
1930 static guint
1931 fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset);
1932
1933 /**
1934  * BACnet Application PDUs chapter 21
1935  * BACnetRecipient::= CHOICE {
1936  *  device  [0] BACnetObjectIdentifier
1937  *  address [1] BACnetAddress
1938  * }
1939  * @param tvb the tv buffer of the current data
1940  * @param pinfo the packet info of the current data
1941  * @param tree the tree to append this item to
1942  * @param offset the offset in the tvb
1943  * @return modified offset
1944  */
1945 static guint
1946 fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1947
1948 /**
1949  * BACnet Application PDUs chapter 21
1950  * BACnetRecipientProcess::= SEQUENCE {
1951  *  recipient   [0] BACnetRecipient
1952  *  processID   [1] Unsigned32
1953  * }
1954  * @param tvb the tv buffer of the current data
1955  * @param pinfo the packet info of the current data
1956  * @param tree the tree to append this item to
1957  * @param offset the offset in the tvb
1958  * @return modified offset
1959  */
1960 static guint
1961 fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1962
1963 static guint
1964 fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1965
1966 #if 0
1967 /**
1968  * BACnetSessionKey ::= SEQUENCE {
1969  *  sessionKey  OCTET STRING (SIZE(8)), -- 56 bits for key, 8 bits for checksum
1970  *  peerAddress BACnetAddress
1971  * }
1972  * @param tvb the tv buffer of the current data
1973  * @param tree the tree to append this item to
1974  * @param offset the offset in the tvb
1975  * @return modified offset
1976  * @todo check if checksum is displayed correctly
1977  */
1978 static guint
1979 fSessionKey(tvbuff_t *tvb, proto_tree *tree, guint offset);
1980 #endif
1981
1982 /**
1983  * BACnetSpecialEvent ::= SEQUENCE {
1984  *  period      CHOICE {
1985  *      calendarEntry       [0] BACnetCalendarEntry,
1986  *      calendarRefernce    [1] BACnetObjectIdentifier
1987  *      },
1988  *      listOfTimeValues    [2] SEQUENCE OF BACnetTimeValue,
1989  *      eventPriority       [3] Unsigned (1..16)
1990  * }
1991  * @param tvb the tv buffer of the current data
1992  * @param pinfo the packet info of the current data
1993  * @param tree the tree to append this item to
1994  * @param offset the offset in the tvb
1995  * @return modified offset
1996  */
1997 static guint
1998 fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1999
2000 /**
2001  * BACnetTimeStamp ::= CHOICE {
2002  *  time            [0] Time,
2003  *  sequenceNumber  [1] Unsigned (0..65535),
2004  *  dateTime        [2] BACnetDateTime
2005  * }
2006  * @param tvb the tv buffer of the current data
2007  * @param pinfo the packet info of the current data
2008  * @param tree the tree to append this item to
2009  * @param offset the offset in the tvb
2010  * @param label the label of this item
2011  * @return modified offset
2012  */
2013 static guint
2014 fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2015
2016 static guint
2017 fEventTimeStamps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2018
2019 /**
2020  * BACnetTimeValue ::= SEQUENCE {
2021  *  time    Time,
2022  *  value   ABSTRACT-SYNTAX.&Type -- any primitive datatype, complex types cannot be decoded
2023  * }
2024  * @param tvb the tv buffer of the current data
2025  * @param pinfo the packet info of the current data
2026  * @param tree the tree to append this item to
2027  * @param offset the offset in the tvb
2028  * @return modified offset
2029  */
2030 static guint
2031 fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2032
2033 #if 0
2034 /**
2035  * BACnetVTSession ::= SEQUENCE {
2036  *  local-vtSessionID   Unsigned8,
2037  *  remote-vtSessionID  Unsigned8,
2038  *  remote-vtAddress    BACnetAddress
2039  * }
2040  * @param tvb the tv buffer of the current data
2041  * @param tree the tree to append this item to
2042  * @param offset the offset in the tvb
2043  * @return modified offset
2044  */
2045 static guint
2046 fVTSession(tvbuff_t *tvb, proto_tree *tree, guint offset);
2047 #endif
2048
2049 /**
2050  * BACnetWeekNDay ::= OCTET STRING (SIZE (3))
2051  * -- first octet month (1..12) January = 1, X'FF' = any month
2052  * -- second octet weekOfMonth where: 1 = days numbered 1-7
2053  * -- 2 = days numbered 8-14
2054  * -- 3 = days numbered 15-21
2055  * -- 4 = days numbered 22-28
2056  * -- 5 = days numbered 29-31
2057  * -- 6 = last 7 days of this month
2058  * -- X'FF' = any week of this month
2059  * -- third octet dayOfWeek (1..7) where 1 = Monday
2060  * -- 7 = Sunday
2061  * -- X'FF' = any day of week
2062  * @param tvb the tv buffer of the current data
2063  * @param pinfo the packet info of the current data
2064  * @param tree the tree to append this item to
2065  * @param offset the offset in the tvb
2066  * @return modified offset
2067  */
2068 static guint
2069 fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2070
2071 /**
2072  * ReadAccessResult ::= SEQUENCE {
2073  *  objectIdentifier            [0] BACnetObjectIdentifier,
2074  *  listOfResults               [1] SEQUENCE OF SEQUENCE {
2075  *      propertyIdentifier      [2] BACnetPropertyIdentifier,
2076  *      propertyArrayIndex      [3] Unsigned OPTIONAL, -- used only with array datatype if omitted with an array the entire array is referenced
2077  *      readResult  CHOICE {
2078  *          propertyValue       [4] ABSTRACT-SYNTAX.&Type,
2079  *          propertyAccessError [5] Error
2080  *      }
2081  *  } OPTIONAL
2082  * }
2083  * @param tvb the tv buffer of the current data
2084  * @param pinfo the packet info of the current data
2085  * @param tree the tree to append this item to
2086  * @param offset the offset in the tvb
2087  * @return modified offset
2088  */
2089 static guint
2090 fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2091
2092 /**
2093  * ReadAccessSpecification ::= SEQUENCE {
2094  *  objectIdentifier         [0] BACnetObjectIdentifier,
2095  *  listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference
2096  * }
2097  * @param tvb the tv buffer of the current data
2098  * @param pinfo the packet info of the current data
2099  * @param subtree the subtree to append this item to
2100  * @param offset the offset in the tvb
2101  * @return modified offset
2102  */
2103 static guint
2104 fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2105
2106 /**
2107  * WriteAccessSpecification ::= SEQUENCE {
2108  *  objectIdentifier [0] BACnetObjectIdentifier,
2109  *  listOfProperty   [1] SEQUENCE OF BACnetPropertyValue
2110  * }
2111  * @param tvb the tv buffer of the current data
2112  * @param pinfo the packet info of the current data
2113  * @param subtree the sub tree to append this item to
2114  * @param offset the offset in the tvb
2115  * @return modified offset
2116  */
2117 static guint
2118 fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2119
2120
2121 /********************************************************* Helper functions *******************************************/
2122
2123 /**
2124  * extracts the tag number from the tag header.
2125  * @param tvb the tv buffer of the current data "TestyVirtualBuffer"
2126  * @param offset the offset in the tvb in actual tvb
2127  * @return Tag Number corresponding to BACnet 20.2.1.2 Tag Number
2128  */
2129 static guint
2130 fTagNo(tvbuff_t *tvb, guint offset);
2131
2132 /**
2133  * splits Tag Header coresponding to 20.2.1 General Rules For BACnet Tags
2134  * @param tvb the tv buffer of the current data = "TestyVirtualBuffer"
2135  * @param pinfo the packet info of the current data = packet info
2136  * @param offset the offset in the tvb = offset in actual tvb
2137  * @return tag_no BACnet 20.2.1.2 Tag Number
2138  * @return class_tag BACnet 20.2.1.1 Class
2139  * @return lvt BACnet 20.2.1.3 Length/Value/Type
2140  * @return offs = length of this header
2141  */
2142
2143 static guint
2144 fTagHeader(tvbuff_t *tvb, packet_info *pinfo, guint offset, guint8 *tag_no, guint8* class_tag, guint32 *lvt);
2145
2146
2147 /**
2148  * adds processID with max 32Bit unsigned Integer Value to tree
2149  * @param tvb the tv buffer of the current data
2150  * @param pinfo the packet info of the current data
2151  * @param tree the tree to append this item to
2152  * @param offset the offset in the tvb
2153  * @return modified offset
2154  */
2155 static guint
2156 fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2157
2158 /**
2159  * adds timeSpan with max 32Bit unsigned Integer Value to tree
2160  * @param tvb the tv buffer of the current data
2161  * @param pinfo the packet info of the current data
2162  * @param tree the tree to append this item to
2163  * @param offset the offset in the tvb
2164  * @return modified offset
2165  */
2166 static guint
2167 fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2168
2169 /**
2170  * BACnet Application PDUs chapter 21
2171  * BACnetPropertyIdentifier::= ENUMERATED {
2172  *   @see bacapp_property_identifier
2173  * }
2174  * @param tvb the tv buffer of the current data
2175  * @param pinfo the packet info of the current data
2176  * @param tree the tree to append this item to
2177  * @param offset the offset in the tvb
2178  * @return modified offset
2179  */
2180 static guint
2181 fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2182
2183 /**
2184  * BACnet Application PDUs chapter 21
2185  * BACnetPropertyArrayIndex::= ENUMERATED {
2186  *   @see bacapp_property_array_index
2187  * }
2188  * @param tvb the tv buffer of the current data
2189  * @param pinfo the packet info of the current data
2190  * @param tree the tree to append this item to
2191  * @param offset the offset in the tvb
2192  * @return modified offset
2193  */
2194 static guint
2195 fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2196
2197 /**
2198  * listOfEventSummaries ::= SEQUENCE OF SEQUENCE {
2199  *  objectIdentifier        [0] BACnetObjectIdentifier,
2200  *  eventState              [1] BACnetEventState,
2201  *  acknowledgedTransitions [2] BACnetEventTransitionBits,
2202  *  eventTimeStamps         [3] SEQURNCE SIZE (3) OF BACnetTimeStamps,
2203  *  notifyType              [4] BACnetNotifyType,
2204  *  eventEnable             [5] BACnetEventTransitionBits,
2205  *  eventPriorities         [6] SEQUENCE SIZE (3) OF Unsigned
2206  * }
2207  * @param tvb the tv buffer of the current data
2208  * @param pinfo the packet info of the current data
2209  * @param tree the tree to append this item to
2210  * @param offset the offset in the tvb
2211  * @return modified offset
2212  */
2213 static guint
2214 flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2215
2216 /**
2217  * SelectionCriteria ::= SEQUENCE {
2218  *  propertyIdentifier [0] BACnetPropertyIdentifier,
2219  *  propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatype
2220  *  relationSpecifier  [2] ENUMERATED { bacapp_relationSpecifier },
2221  *  comparisonValue    [3] ABSTRACT-SYNTAX.&Type
2222  * }
2223  * @param tvb the tv buffer of the current data
2224  * @param pinfo the packet info of the current data
2225  * @param tree the tree to append this item to
2226  * @param offset the offset in the tvb
2227  * @return modified offset
2228  */
2229 static guint
2230 fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2231
2232 /**
2233  * objectSelectionCriteria ::= SEQUENCE {
2234  *  selectionLogic          [0] ENUMERATED { bacapp_selectionLogic },
2235  *  listOfSelectionCriteria [1] SelectionCriteria
2236  * }
2237  * @param tvb the tv buffer of the current data
2238  * @param pinfo the packet info of the current data
2239  * @param subtree the sub tree to append this item to
2240  * @param offset the offset in the tvb
2241  * @return modified offset
2242  */
2243 static guint
2244 fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2245
2246 /**
2247  * BACnet-Error ::= SEQUENCE {
2248  *    error-class ENUMERATED {},
2249  *    error-code  ENUMERATED {}
2250  *    }
2251  * }
2252  * @param tvb the tv buffer of the current data
2253  * @param pinfo the packet info of the current data
2254  * @param tree the tree to append this item to
2255  * @param offset the offset in the tvb
2256  * @return modified offset
2257  */
2258 static guint
2259 fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2260
2261 /**
2262  * Generic handler for context tagged values.  Mostly for handling
2263  * vendor-defined properties and services.
2264  * @param tvb the tv buffer of the current data
2265  * @param pinfo the packet info of the current data
2266  * @param tree the tree to append this item to
2267  * @param offset the offset in the tvb
2268  * @return modified offset
2269  * @todo beautify this ugly construct
2270  */
2271 static guint
2272 fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2273
2274 /**
2275  * realizes some ABSTRACT-SYNTAX.&Type
2276  * @param tvb the tv buffer of the current data
2277  * @param pinfo the packet info of the current data
2278  * @param tree the tree to append this item to
2279  * @param offset the offset in the tvb
2280  * @return modified offset
2281  * @todo beautify this ugly construct
2282  */
2283 static guint
2284 fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2285
2286
2287 static guint
2288 fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label,
2289     const value_string *src);
2290
2291 /**
2292  * register_bacapp
2293  */
2294 void
2295 proto_register_bacapp(void);
2296
2297 /**
2298  * proto_reg_handoff_bacapp
2299  */
2300 void
2301 proto_reg_handoff_bacapp(void);
2302
2303 /* <<<< formerly bacapp.h */
2304
2305 /* reassembly table for segmented messages */
2306 static reassembly_table msg_reassembly_table;
2307
2308 /* some necessary forward function prototypes */
2309 static guint
2310 fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
2311     const gchar *label, const value_string *vs);
2312
2313 static const char *bacapp_unknown_service_str = "unknown service";  /* Usage: no format specifiers */
2314 static const char ASHRAE_Reserved_Fmt[] = "(%d) Reserved for Use by ASHRAE";
2315 static const char Vendor_Proprietary_Fmt[] = "(%d) Vendor Proprietary Value";
2316
2317 static const value_string
2318 BACnetTypeName[] = {
2319     { 0, "Confirmed-REQ"},
2320     { 1, "Unconfirmed-REQ"},
2321     { 2, "Simple-ACK"},
2322     { 3, "Complex-ACK"},
2323     { 4, "Segment-ACK"},
2324     { 5, "Error"},
2325     { 6, "Reject"},
2326     { 7, "Abort"},
2327     { 0, NULL }
2328 };
2329
2330 static const true_false_string segments_follow = {
2331     "Segmented Request",
2332     "Unsegmented Request"
2333 };
2334
2335 static const true_false_string more_follow = {
2336     "More Segments Follow",
2337     "No More Segments Follow"
2338 };
2339
2340 static const true_false_string segmented_accept = {
2341     "Segmented Response accepted",
2342     "Segmented Response not accepted"
2343 };
2344
2345 static const true_false_string
2346 BACnetTagClass = {
2347     "Context Specific Tag",
2348     "Application Tag"
2349 };
2350
2351 static const value_string
2352 BACnetMaxSegmentsAccepted [] = {
2353     { 0,  "Unspecified"},
2354     { 1,  "2 segments"},
2355     { 2,  "4 segments"},
2356     { 3,  "8 segments"},
2357     { 4, "16 segments"},
2358     { 5, "32 segments"},
2359     { 6, "64 segments"},
2360     { 7, "Greater than 64 segments"},
2361     { 0, NULL }
2362 };
2363
2364 static const value_string
2365 BACnetMaxAPDULengthAccepted [] = {
2366     {  0, "Up to MinimumMessageSize (50 octets)"},
2367     {  1, "Up to 128 octets"},
2368     {  2, "Up to 206 octets (fits in a LonTalk frame)"},
2369     {  3, "Up to 480 octets (fits in an ARCNET frame)"},
2370     {  4, "Up to 1024 octets"},
2371     {  5, "Up to 1476 octets (fits in an ISO 8802-3 frame)"},
2372     {  6, "reserved by ASHRAE"},
2373     {  7, "reserved by ASHRAE"},
2374     {  8, "reserved by ASHRAE"},
2375     {  9, "reserved by ASHRAE"},
2376     { 10, "reserved by ASHRAE"},
2377     { 11, "reserved by ASHRAE"},
2378     { 12, "reserved by ASHRAE"},
2379     { 13, "reserved by ASHRAE"},
2380     { 14, "reserved by ASHRAE"},
2381     { 15, "reserved by ASHRAE"},
2382     { 0, NULL}
2383 };
2384
2385 static const value_string
2386 BACnetRejectReason [] = {
2387     {0, "other"},
2388     {1, "buffer-overflow"},
2389     {2, "inconsistent-parameters"},
2390     {3, "invalid-parameter-data-type"},
2391     {4, "invalid-tag"},
2392     {5, "missing-required-parameter"},
2393     {6, "parameter-out-of-range"},
2394     {7, "too-many-arguments"},
2395     {8, "undefined-enumeration"},
2396     {9, "unrecognized-service"},
2397     {0, NULL}
2398 };
2399
2400 static const value_string
2401 BACnetRestartReason [] = {
2402     { 0, "unknown"},
2403     { 1, "coldstart"},
2404     { 2, "warmstart"},
2405     { 3, "detected-power-lost"},
2406     { 4, "detected-powered-off"},
2407     { 5, "hardware-watchdog"},
2408     { 6, "software-watchdog"},
2409     { 7, "suspended"},
2410     { 0, NULL}
2411 };
2412
2413 static const value_string
2414 BACnetApplicationTagNumber [] = {
2415     {  0, "Null"},
2416     {  1, "Boolean"},
2417     {  2, "Unsigned Integer"},
2418     {  3, "Signed Integer (2's complement notation)"},
2419     {  4, "Real (ANSI/IEE-754 floating point)"},
2420     {  5, "Double (ANSI/IEE-754 double precision floating point)"},
2421     {  6, "Octet String"},
2422     {  7, "Character String"},
2423     {  8, "Bit String"},
2424     {  9, "Enumerated"},
2425     { 10, "Date"},
2426     { 11, "Time"},
2427     { 12, "BACnetObjectIdentifier"},
2428     { 13, "reserved by ASHRAE"},
2429     { 14, "reserved by ASHRAE"},
2430     { 15, "reserved by ASHRAE"},
2431     { 0,  NULL}
2432 };
2433
2434 static const value_string
2435 BACnetAction [] = {
2436     { 0, "direct"},
2437     { 1, "reverse"},
2438     { 0, NULL}
2439 };
2440
2441 static const value_string
2442 BACnetAccessEvent [] = {
2443     {  0, "none"},
2444     {  1, "granted"},
2445     {  2, "muster"},
2446     {  3, "passback-detected"},
2447     {  4, "duress"},
2448     {  5, "trace"},
2449     {  6, "lockout-max-attempts"},
2450     {  7, "lockout-other"},
2451     {  8, "lockout-relinquished"},
2452     {  9, "lockout-by-higher-priority"},
2453     { 10, "out-of-service"},
2454     { 11, "out-of-service-relinquished"},
2455     { 12, "accompaniment-by"},
2456     { 13, "authentication-factor-read"},
2457     { 14, "authorization-delayed"},
2458     { 15, "verification-required"},
2459     /* Enumerated values 128-511 are used for events
2460      * which indicate that access has been denied. */
2461     { 128, "denied-deny-all"},
2462     { 129, "denied-unknown-credential"},
2463     { 130, "denied-authentication-unavailable"},
2464     { 131, "denied-authentication-factor-timeout"},
2465     { 132, "denied-incorrect-authentication-factor"},
2466     { 133, "denied-zone-no-access-rights"},
2467     { 134, "denied-point-no-access-rights"},
2468     { 135, "denied-no-access-rights"},
2469     { 136, "denied-out-of-time-range"},
2470     { 137, "denied-threat-level"},
2471     { 138, "denied-passback"},
2472     { 139, "denied-unexpected-location-usage"},
2473     { 140, "denied-max-attempts"},
2474     { 141, "denied-lower-occupancy-limit"},
2475     { 142, "denied-upper-occupancy-limit"},
2476     { 143, "denied-authentication-factor-lost"},
2477     { 144, "denied-authentication-factor-stolen"},
2478     { 145, "denied-authentication-factor-damaged"},
2479     { 146, "denied-authentication-factor-destroyed"},
2480     { 147, "denied-authentication-factor-disabled"},
2481     { 148, "denied-authentication-factor-error"},
2482     { 149, "denied-credential-unassigned"},
2483     { 150, "denied-credential-not-provisioned"},
2484     { 151, "denied-credential-not-yet-active"},
2485     { 152, "denied-credential-expired"},
2486     { 153, "denied-credential-manual-disable"},
2487     { 154, "denied-credential-lockout"},
2488     { 155, "denied-credential-max-days"},
2489     { 156, "denied-credential-max-uses"},
2490     { 157, "denied-credential-inactivity"},
2491     { 158, "denied-credential-disabled"},
2492     { 159, "denied-no-accompaniment"},
2493     { 160, "denied-incorrect-accompaniment"},
2494     { 161, "denied-lockout"},
2495     { 162, "denied-verification-failed"},
2496     { 163, "denied-verification-timeout"},
2497     { 164, "denied-other"},
2498     { 0,  NULL}
2499 /* Enumerated values 0-512 are reserved for definition by ASHRAE.
2500    Enumerated values 512-65535 may be used by others subject to
2501    procedures and constraints described in Clause 23. */
2502 };
2503
2504 static const value_string
2505 BACnetFileAccessMethod [] = {
2506     { 0, "record-access"},
2507     { 1, "stream-access"},
2508     { 0, NULL}
2509 };
2510
2511 /* For some reason, BACnet defines the choice parameter
2512    in the file read and write services backwards from the
2513    BACnetFileAccessMethod enumeration.
2514 */
2515 static const value_string
2516 BACnetFileAccessOption [] = {
2517     { 0, "stream access"},
2518     { 1, "record access"},
2519     { 0, NULL}
2520 };
2521
2522 static const value_string
2523 BACnetFileStartOption [] = {
2524     { 0, "File Start Position: "},
2525     { 1, "File Start Record: "},
2526     { 0, NULL}
2527 };
2528
2529 static const value_string
2530 BACnetFileRequestCount [] = {
2531     { 0, "Requested Octet Count: "},
2532     { 1, "Requested Record Count: "},
2533     { 0, NULL}
2534 };
2535
2536 static const value_string
2537 BACnetFileWriteInfo [] = {
2538     { 0, "File Data: "},
2539     { 1, "Record Count: "},
2540     { 0, NULL}
2541 };
2542
2543 static const value_string
2544 BACnetAbortReason [] = {
2545     { 0, "other"},
2546     { 1, "buffer-overflow"},
2547     { 2, "invalid-apdu-in-this-state"},
2548     { 3, "preempted-by-higher-priority-task"},
2549     { 4, "segmentation-not-supported"},
2550     { 0, NULL}
2551 };
2552
2553 static const value_string
2554 BACnetLifeSafetyMode [] = {
2555     {  0, "off"},
2556     {  1, "on"},
2557     {  2, "test"},
2558     {  3, "manned"},
2559     {  4, "unmanned"},
2560     {  5, "armed"},
2561     {  6, "disarmed"},
2562     {  7, "prearmed"},
2563     {  8, "slow"},
2564     {  9, "fast"},
2565     { 10, "disconnected"},
2566     { 11, "enabled"},
2567     { 12, "disabled"},
2568     { 13, "atomic-release-disabled"},
2569     { 14, "default"},
2570     { 0,  NULL}
2571 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2572    Enumerated values 256-65535 may be used by others subject to
2573    procedures and constraints described in Clause 23. */
2574 };
2575
2576 static const value_string
2577 BACnetLifeSafetyOperation [] = {
2578     { 0, "none"},
2579     { 1, "silence"},
2580     { 2, "silence-audible"},
2581     { 3, "silence-visual"},
2582     { 4, "reset"},
2583     { 5, "reset-alarm"},
2584     { 6, "reset-fault"},
2585     { 7, "unsilence"},
2586     { 8, "unsilence-audible"},
2587     { 9, "unsilence-visual"},
2588     { 0, NULL}
2589 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
2590    Enumerated values 64-65535 may be used by others subject to
2591    procedures and constraints described in Clause 23. */
2592 };
2593
2594 #if 0
2595 static const value_string
2596 BACnetLimitEnable [] = {
2597     { 0, "lowLimitEnable"},
2598     { 1, "highLimitEnable"},
2599     { 0, NULL}
2600 };
2601 #endif
2602
2603 static const value_string
2604 BACnetLifeSafetyState [] = {
2605     {  0, "quiet"},
2606     {  1, "pre-alarm"},
2607     {  2, "alarm"},
2608     {  3, "fault"},
2609     {  4, "fault-pre-alarm"},
2610     {  5, "fault-alarm"},
2611     {  6, "not-ready"},
2612     {  7, "active"},
2613     {  8, "tamper"},
2614     {  9, "test-alarm"},
2615     { 10, "test-active"},
2616     { 11, "test-fault"},
2617     { 12, "test-fault-alarm"},
2618     { 13, "holdup"},
2619     { 14, "duress"},
2620     { 15, "tamper-alarm"},
2621     { 16, "abnormal"},
2622     { 17, "emergency-power"},
2623     { 18, "delayed"},
2624     { 19, "blocked"},
2625     { 20, "local-alarm"},
2626     { 21, "general-alarm"},
2627     { 22, "supervisory"},
2628     { 23, "test-supervisory"},
2629     { 0,  NULL}
2630 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2631    Enumerated values 256-65535 may be used by others subject to
2632    procedures and constraints described in Clause 23. */
2633 };
2634
2635 static const value_string
2636 BACnetConfirmedServiceChoice [] = {
2637     {  0, "acknowledgeAlarm"},
2638     {  1, "confirmedCOVNotification"},
2639     {  2, "confirmedEventNotification"},
2640     {  3, "getAlarmSummary"},
2641     {  4, "getEnrollmentSummary"},
2642     {  5, "subscribeCOV"},
2643     {  6, "atomicReadFile"},
2644     {  7, "atomicWriteFile"},
2645     {  8, "addListElement"},
2646     {  9, "removeListElement"},
2647     { 10, "createObject"},
2648     { 11, "deleteObject"},
2649     { 12, "readProperty"},
2650     { 13, "readPropertyConditional"},
2651     { 14, "readPropertyMultiple"},
2652     { 15, "writeProperty"},
2653     { 16, "writePropertyMultiple"},
2654     { 17, "deviceCommunicationControl"},
2655     { 18, "confirmedPrivateTransfer"},
2656     { 19, "confirmedTextMessage"},
2657     { 20, "reinitializeDevice"},
2658     { 21, "vtOpen"},
2659     { 22, "vtClose"},
2660     { 23, "vtData"},
2661     { 24, "authenticate"},
2662     { 25, "requestKey"},
2663     { 26, "readRange"},
2664     { 27, "lifeSafetyOperation"},
2665     { 28, "subscribeCOVProperty"},
2666     { 29, "getEventInformation"},
2667     { 30, "reserved by ASHRAE"},
2668     { 0,  NULL}
2669 };
2670
2671 static const value_string
2672 BACnetReliability [] = {
2673     {  0, "no-fault-detected"},
2674     {  1, "no-sensor"},
2675     {  2, "over-range"},
2676     {  3, "under-range"},
2677     {  4, "open-loop"},
2678     {  5, "shorted-loop"},
2679     {  6, "no-output"},
2680     {  7, "unreliable-other"},
2681     {  8, "process-error"},
2682     {  9, "multi-state-fault"},
2683     { 10, "configuration-error"},
2684     /* enumeration value 11 is reserved for a future addendum */
2685     { 12, "communication-failure"},
2686     { 13, "member-fault"},
2687     { 0,  NULL}
2688 };
2689
2690 static const value_string
2691 BACnetUnconfirmedServiceChoice [] = {
2692     { 0, "i-Am"},
2693     { 1, "i-Have"},
2694     { 2, "unconfirmedCOVNotification"},
2695     { 3, "unconfirmedEventNotification"},
2696     { 4, "unconfirmedPrivateTransfer"},
2697     { 5, "unconfirmedTextMessage"},
2698     { 6, "timeSynchronization"},
2699     { 7, "who-Has"},
2700     { 8, "who-Is"},
2701     { 9, "utcTimeSynchronization"},
2702     { 0, NULL}
2703 };
2704
2705 #if 0
2706 static const value_string
2707 BACnetUnconfirmedServiceRequest [] = {
2708     { 0, "i-Am-Request"},
2709     { 1, "i-Have-Request"},
2710     { 2, "unconfirmedCOVNotification-Request"},
2711     { 3, "unconfirmedEventNotification-Request"},
2712     { 4, "unconfirmedPrivateTransfer-Request"},
2713     { 5, "unconfirmedTextMessage-Request"},
2714     { 6, "timeSynchronization-Request"},
2715     { 7, "who-Has-Request"},
2716     { 8, "who-Is-Request"},
2717     { 9, "utcTimeSynchonization-Request"},
2718     { 0, NULL}
2719 };
2720 #endif
2721
2722 static const value_string
2723 BACnetObjectType [] = {
2724     {  0, "analog-input"},
2725     {  1, "analog-output"},
2726     {  2, "analog-value"},
2727     {  3, "binary-input"},
2728     {  4, "binary-output"},
2729     {  5, "binary-value"},
2730     {  6, "calendar"},
2731     {  7, "command"},
2732     {  8, "device"},
2733     {  9, "event-enrollment"},
2734     { 10, "file"},
2735     { 11, "group"},
2736     { 12, "loop"},
2737     { 13, "multi-state-input"},
2738     { 14, "multi-state-output"},
2739     { 15, "notification-class"},
2740     { 16, "program"},
2741     { 17, "schedule"},
2742     { 18, "averaging"},
2743     { 19, "multi-state-value"},
2744     { 20, "trend-log"},
2745     { 21, "life-safety-point"},
2746     { 22, "life-safety-zone"},
2747     { 23, "accumulator"},
2748     { 24, "pulse-converter"},
2749     { 25, "event-log"},
2750     { 26, "global-group"},
2751     { 27, "trend-log-multiple"},
2752     { 28, "load-control"},
2753     { 29, "structured-view"},
2754     { 30, "access-door"},     /* 30-37 added with addanda 135-2008j */
2755     /* value 31 is unassigned */
2756     { 32, "access-credential"},
2757     { 33, "access-point"},
2758     { 34, "access-rights"},
2759     { 35, "access-user"},
2760     { 36, "access-zone"},
2761     { 37, "credential-data-input"},
2762     { 38, "network-security"},
2763     { 39, "bitstring-value"},     /* 39-50 added with addenda 135-2008w */
2764     { 40, "characterstring-value"},
2765     { 41, "date-pattern-value"},
2766     { 42, "date-value"},
2767     { 43, "datetime-pattern-value"},
2768     { 44, "datetime-value"},
2769     { 45, "integer-value"},
2770     { 46, "large-analog-value"},
2771     { 47, "octetstring-value"},
2772     { 48, "positive-integer-value"},
2773     { 49, "time-pattern-value"},
2774     { 50, "time-value"},
2775     { 0,  NULL}
2776 /* Enumerated values 0-127 are reserved for definition by ASHRAE.
2777    Enumerated values 128-1023 may be used by others subject to
2778    the procedures and constraints described in Clause 23. */
2779 };
2780
2781 static const value_string
2782 BACnetEngineeringUnits [] = {
2783     {   0, "Sq Meters"},
2784     {   1, "Sq Feet"},
2785     {   2, "Milliamperes"},
2786     {   3, "Amperes"},
2787     {   4, "Ohms"},
2788     {   5, "Volts"},
2789     {   6, "Kilovolts"},
2790     {   7, "Megavolts"},
2791     {   8, "Volt Amperes"},
2792     {   9, "Kilovolt Amperes"},
2793     {  10, "Megavolt Amperes"},
2794     {  11, "Volt Amperes Reactive"},
2795     {  12, "Kilovolt Amperes Reactive"},
2796     {  13, "Megavolt Amperes Reactive"},
2797     {  14, "Degrees Phase"},
2798     {  15, "Power Factor"},
2799     {  16, "Joules"},
2800     {  17, "Kilojoules"},
2801     {  18, "Watt Hours"},
2802     {  19, "Kilowatt Hours"},
2803     {  20, "BTUs"},
2804     {  21, "Therms"},
2805     {  22, "Ton Hours"},
2806     {  23, "Joules Per Kg Dry Air"},
2807     {  24, "BTUs Per Pound Dry Air"},
2808     {  25, "Cycles Per Hour"},
2809     {  26, "Cycles Per Minute"},
2810     {  27, "Hertz"},
2811     {  28, "Grams Of Water Per Kilogram Dry Air"},
2812     {  29, "Relative Humidity"},
2813     {  30, "Millimeters"},
2814     {  31, "Meters"},
2815     {  32, "Inches"},
2816     {  33, "Feed"},
2817     {  34, "Watts Per Sq Foot"},
2818     {  35, "Watts Per Sq meter"},
2819     {  36, "Lumens"},
2820     {  37, "Lux"},
2821     {  38, "Foot Candles"},
2822     {  39, "Kilograms"},
2823     {  40, "Pounds Mass"},
2824     {  41, "Tons"},
2825     {  42, "Kgs per Second"},
2826     {  43, "Kgs Per Minute"},
2827     {  44, "Kgs Per Hour"},
2828     {  45, "Pounds Mass Per Minute"},
2829     {  46, "Pounds Mass Per Hour"},
2830     {  47, "Watt"},
2831     {  48, "Kilowatts"},
2832     {  49, "Megawatts"},
2833     {  50, "BTUs Per Hour"},
2834     {  51, "Horsepower"},
2835     {  52, "Tons Refrigeration"},
2836     {  53, "Pascals"},
2837     {  54, "Kilopascals"},
2838     {  55, "Bars"},
2839     {  56, "Pounds Force Per Square Inch"},
2840     {  57, "Centimeters Of Water"},
2841     {  58, "Inches Of Water"},
2842     {  59, "Millimeters Of Mercury"},
2843     {  60, "Centimeters Of Mercury"},
2844     {  61, "Inches Of Mercury"},
2845     {  62, "Degrees Celsius"},
2846     {  63, "Degrees Kelvin"},
2847     {  64, "Degrees Fahrenheit"},
2848     {  65, "Degree Days Celsius"},
2849     {  66, "Degree Days Fahrenheit"},
2850     {  67, "Years"},
2851     {  68, "Months"},
2852     {  69, "Weeks"},
2853     {  70, "Days"},
2854     {  71, "Hours"},
2855     {  72, "Minutes"},
2856     {  73, "Seconds"},
2857     {  74, "Meters Per Second"},
2858     {  75, "Kilometers Per Hour"},
2859     {  76, "Feed Per Second"},
2860     {  77, "Feet Per Minute"},
2861     {  78, "Miles Per Hour"},
2862     {  79, "Cubic Feet"},
2863     {  80, "Cubic Meters"},
2864     {  81, "Imperial Gallons"},
2865     {  82, "Liters"},
2866     {  83, "US Gallons"},
2867     {  84, "Cubic Feet Per Minute"},
2868     {  85, "Cubic Meters Per Second"},
2869     {  86, "Imperial Gallons Per Minute"},
2870     {  87, "Liters Per Second"},
2871     {  88, "Liters Per Minute"},
2872     {  89, "US Gallons Per Minute"},
2873     {  90, "Degrees Angular"},
2874     {  91, "Degrees Celsius Per Hour"},
2875     {  92, "Degrees Celsius Per Minute"},
2876     {  93, "Degrees Fahrenheit Per Hour"},
2877     {  94, "Degrees Fahrenheit Per Minute"},
2878     {  95, "No Units"},
2879     {  96, "Parts Per Million"},
2880     {  97, "Parts Per Billion"},
2881     {  98, "Percent"},
2882     {  99, "Pecent Per Second"},
2883     { 100, "Per Minute"},
2884     { 101, "Per Second"},
2885     { 102, "Psi Per Degree Fahrenheit"},
2886     { 103, "Radians"},
2887     { 104, "Revolutions Per Min"},
2888     { 105, "Currency1"},
2889     { 106, "Currency2"},
2890     { 107, "Currency3"},
2891     { 108, "Currency4"},
2892     { 109, "Currency5"},
2893     { 110, "Currency6"},
2894     { 111, "Currency7"},
2895     { 112, "Currency8"},
2896     { 113, "Currency9"},
2897     { 114, "Currency10"},
2898     { 115, "Sq Inches"},
2899     { 116, "Sq Centimeters"},
2900     { 117, "BTUs Per Pound"},
2901     { 118, "Centimeters"},
2902     { 119, "Pounds Mass Per Second"},
2903     { 120, "Delta Degrees Fahrenheit"},
2904     { 121, "Delta Degrees Kelvin"},
2905     { 122, "Kilohms"},
2906     { 123, "Megohms"},
2907     { 124, "Millivolts"},
2908     { 125, "Kilojoules Per Kg"},
2909     { 126, "Megajoules"},
2910     { 127, "Joules Per Degree Kelvin"},
2911     { 128, "Joules Per Kg Degree Kelvin"},
2912     { 129, "Kilohertz"},
2913     { 130, "Megahertz"},
2914     { 131, "Per Hour"},
2915     { 132, "Milliwatts"},
2916     { 133, "Hectopascals"},
2917     { 134, "Millibars"},
2918     { 135, "Cubic Meters Per Hour"},
2919     { 136, "Liters Per Hour"},
2920     { 137, "KWatt Hours Per Square Meter"},
2921     { 138, "KWatt Hours Per Square Foot"},
2922     { 139, "Megajoules Per Square Meter"},
2923     { 140, "Megajoules Per Square Foot"},
2924     { 141, "Watts Per Sq Meter Degree Kelvin"},
2925     { 142, "Cubic Feet Per Second"},
2926     { 143, "Percent Obstruction Per Foot"},
2927     { 144, "Percent Obstruction Per Meter"},
2928     { 145, "milliohms"},
2929     { 146, "megawatt-hours"},
2930     { 147, "kilo-btus"},
2931     { 148, "mega-btus"},
2932     { 149, "kilojoules-per-kilogram-dry-air"},
2933     { 150, "megajoules-per-kilogram-dry-air"},
2934     { 151, "kilojoules-per-degree-Kelvin"},
2935     { 152, "megajoules-per-degree-Kelvin"},
2936     { 153, "newton"},
2937     { 154, "grams-per-second"},
2938     { 155, "grams-per-minute"},
2939     { 156, "tons-per-hour"},
2940     { 157, "kilo-btus-per-hour"},
2941     { 158, "hundredths-seconds"},
2942     { 159, "milliseconds"},
2943     { 160, "newton-meters"},
2944     { 161, "millimeters-per-second"},
2945     { 162, "millimeters-per-minute"},
2946     { 163, "meters-per-minute"},
2947     { 164, "meters-per-hour"},
2948     { 165, "cubic-meters-per-minute"},
2949     { 166, "meters-per-second-per-second"},
2950     { 167, "amperes-per-meter"},
2951     { 168, "amperes-per-square-meter"},
2952     { 169, "ampere-square-meters"},
2953     { 170, "farads"},
2954     { 171, "henrys"},
2955     { 172, "ohm-meters"},
2956     { 173, "siemens"},
2957     { 174, "siemens-per-meter"},
2958     { 175, "teslas"},
2959     { 176, "volts-per-degree-Kelvin"},
2960     { 177, "volts-per-meter"},
2961     { 178, "webers"},
2962     { 179, "candelas"},
2963     { 180, "candelas-per-square-meter"},
2964     { 181, "degrees-Kelvin-per-hour"},
2965     { 182, "degrees-Kelvin-per-minute"},
2966     { 183, "joule-seconds"},
2967     { 184, "radians-per-second"},
2968     { 185, "square-meters-per-Newton"},
2969     { 186, "kilograms-per-cubic-meter"},
2970     { 187, "newton-seconds"},
2971     { 188, "newtons-per-meter"},
2972     { 189, "watts-per-meter-per-degree-Kelvin"},
2973     { 190, "micro-siemens"},
2974     { 191, "cubic-feet-per-hour"},
2975     { 192, "us-gallons-per-hour"},
2976     { 193, "kilometers"},
2977     { 194, "micrometers"},
2978     { 195, "grams"},
2979     { 196, "milligrams"},
2980     { 197, "milliliters"},
2981     { 198, "milliliters-per-second"},
2982     { 199, "decibels"},
2983     { 200, "decibels-millivolt"},
2984     { 201, "decibels-volt"},
2985     { 202, "millisiemens"},
2986     { 203, "watt-hours-reactive"},
2987     { 204, "kilowatt-hours-reactive"},
2988     { 205, "megawatt-hours-reactive"},
2989     { 206, "millimeters-of-water"},
2990     { 207, "per-mille"},
2991     { 208, "grams-per-gram"},
2992     { 209, "kilograms-per-kilogram"},
2993     { 210, "grams-per-kilogram"},
2994     { 211, "milligrams-per-gram"},
2995     { 212, "milligrams-per-kilogram"},
2996     { 213, "grams-per-milliliter"},
2997     { 214, "grams-per-liter"},
2998     { 215, "milligrams-per-liter"},
2999     { 216, "micrograms-per-liter"},
3000     { 217, "grams-per-cubic-meter"},
3001     { 218, "milligrams-per-cubic-meter"},
3002     { 219, "micrograms-per-cubic-meter"},
3003     { 220, "nanograms-per-cubic-meter"},
3004     { 221, "grams-per-cubic-centimeter"},
3005     { 222, "becquerels"},
3006     { 223, "kilobecquerels"},
3007     { 224, "megabecquerels"},
3008     { 225, "gray"},
3009     { 226, "milligray"},
3010     { 227, "microgray"},
3011     { 228, "sieverts"},
3012     { 229, "millisieverts"},
3013     { 230, "microsieverts"},
3014     { 231, "microsieverts-per-hour"},
3015     { 232, "decibels-a"},
3016     { 233, "nephelometric-turbidity-unit"},
3017     { 234, "pH"},
3018     { 235, "grams-per-square-meter"},
3019     { 236, "minutes-per-degree-kelvin"},
3020     { 0,   NULL}
3021 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
3022    Enumerated values 256-65535 may be used by others subject to
3023    the procedures and constraints described in Clause 23. */
3024 };
3025
3026 static const value_string
3027 BACnetErrorCode [] = {
3028     {   0, "other"},
3029     {   1, "authentication-failed"},
3030     {   2, "configuration-in-progress"},
3031     {   3, "device-busy"},
3032     {   4, "dynamic-creation-not-supported"},
3033     {   5, "file-access-denied"},
3034     {   6, "incompatible-security-levels"},
3035     {   7, "inconsistent-parameters"},
3036     {   8, "inconsistent-selection-criterion"},
3037     {   9, "invalid-data-type"},
3038     {  10, "invalid-file-access-method"},
3039     {  11, "invalid-file-start-position"},
3040     {  12, "invalid-operator-name"},
3041     {  13, "invalid-parameter-data-type"},
3042     {  14, "invalid-time-stamp"},
3043     {  15, "key-generation-error"},
3044     {  16, "missing-required-parameter"},
3045     {  17, "no-objects-of-specified-type"},
3046     {  18, "no-space-for-object"},
3047     {  19, "no-space-to-add-list-element"},
3048     {  20, "no-space-to-write-property"},
3049     {  21, "no-vt-sessions-available"},
3050     {  22, "property-is-not-a-list"},
3051     {  23, "object-deletion-not-permitted"},
3052     {  24, "object-identifier-already-exists"},
3053     {  25, "operational-problem"},
3054     {  26, "password-failure"},
3055     {  27, "read-access-denied"},
3056     {  28, "security-not-supported"},
3057     {  29, "service-request-denied"},
3058     {  30, "timeout"},
3059     {  31, "unknown-object"},
3060     {  32, "unknown-property"},
3061     {  33, "removed enumeration"},
3062     {  34, "unknown-vt-class"},
3063     {  35, "unknown-vt-session"},
3064     {  36, "unsupported-object-type"},
3065     {  37, "value-out-of-range"},
3066     {  38, "vt-session-already-closed"},
3067     {  39, "vt-session-termination-failure"},
3068     {  40, "write-access-denied"},
3069     {  41, "character-set-not-supported"},
3070     {  42, "invalid-array-index"},
3071     {  43, "cov-subscription-failed"},
3072     {  44, "not-cov-property"},
3073     {  45, "optional-functionality-not-supported"},
3074     {  46, "invalid-configuration-data"},
3075     {  47, "datatype-not-supported"},
3076     {  48, "duplicate-name"},
3077     {  49, "duplicate-object-id"},
3078     {  50, "property-is-not-an-array"},
3079     {  73, "invalid-event-state"},
3080     {  74, "no-alarm-configured"},
3081     {  75, "log-buffer-full"},
3082     {  76, "logged-value-purged"},
3083     {  77, "no-property-specified"},
3084     {  78, "not-configured-for-triggered-logging"},
3085     {  79, "unknown-subscription"},
3086     {  80, "parameter-out-of-range"},
3087     {  81, "list-element-not-found"},
3088     {  82, "busy"},
3089     {  83, "communication-disabled"},
3090     {  84, "success"},
3091     {  85, "access-denied"},
3092     {  86, "bad-destination-address"},
3093     {  87, "bad-destination-device-id"},
3094     {  88, "bad-signature"},
3095     {  89, "bad-source-address"},
3096     {  90, "bad-timestamp"},
3097     {  91, "cannot-use-key"},
3098     {  92, "cannot-verify-message-id"},
3099     {  93, "correct-key-revision"},
3100     {  94, "destination-device-id-required"},
3101     {  95, "duplicate-message"},
3102     {  96, "encryption-not-configured"},
3103     {  97, "encryption-required"},
3104     {  98, "incorrect-key"},
3105     {  99, "invalid-key-data"},
3106     { 100, "key-update-in-progress"},
3107     { 101, "malformed-message"},
3108     { 102, "not-key-server"},
3109     { 103, "security-not-configured"},
3110     { 104, "source-security-required"},
3111     { 105, "too-many-keys"},
3112     { 106, "unknown-authentication-type"},
3113     { 107, "unknown-key"},
3114     { 108, "unknown-key-revision"},
3115     { 109, "unknown-source-message"},
3116     { 110, "not-router-to-dnet"},
3117     { 111, "router-busy"},
3118     { 112, "unknown-network-message"},
3119     { 113, "message-too-long"},
3120     { 114, "security-error"},
3121     { 115, "addressing-error"},
3122     { 116, "write-bdt-failed"},
3123     { 117, "read-bdt-failed"},
3124     { 118, "register-foreign-device-failed"},
3125     { 119, "read-fdt-failed"},
3126     { 120, "delete-fdt-entry-failed"},
3127     { 121, "distribute-broadcast-failed"},
3128     { 122, "unknown-file-size"},
3129     { 123, "abort-apdu-too-long"},
3130     { 124, "abort-application-exceeded-reply-time"},
3131     { 125, "abort-out-of-resources"},
3132     { 126, "abort-tsm-timeout"},
3133     { 127, "abort-window-size-out-of-range"},
3134     { 128, "file-full"},
3135     { 129, "inconsistent-configuration"},
3136     { 130, "inconsistent-object-type"},
3137     { 131, "internal-error"},
3138     { 132, "not-configured"},
3139     { 133, "out-of-memory"},
3140     { 134, "value-too-long"},
3141     { 135, "abort-insufficient-security"},
3142     { 136, "abort-security-error"},
3143     { 0,   NULL}
3144 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
3145    Enumerated values 256-65535 may be used by others subject to the
3146    procedures and constraints described in Clause 23. */
3147 };
3148
3149 static const value_string
3150 BACnetPropertyIdentifier [] = {
3151     {   0, "acked-transition"},
3152     {   1, "ack-required"},
3153     {   2, "action"},
3154     {   3, "action-text"},
3155     {   4, "active-text"},
3156     {   5, "active-vt-session"},
3157     {   6, "alarm-value"},
3158     {   7, "alarm-values"},
3159     {   8, "all"},
3160     {   9, "all-writes-successful"},
3161     {  10, "apdu-segment-timeout"},
3162     {  11, "apdu-timeout"},
3163     {  12, "application-software-version"},
3164     {  13, "archive"},
3165     {  14, "bias"},
3166     {  15, "change-of-state-count"},
3167     {  16, "change-of-state-time"},
3168     {  17, "notification-class"},
3169     {  18, "the property in this place was deleted"},
3170     {  19, "controlled-variable-reference"},
3171     {  20, "controlled-variable-units"},
3172     {  21, "controlled-variable-value"},
3173     {  22, "cov-increment"},
3174     {  23, "datelist"},
3175     {  24, "daylights-savings-status"},
3176     {  25, "deadband"},
3177     {  26, "derivative-constant"},
3178     {  27, "derivative-constant-units"},
3179     {  28, "description"},
3180     {  29, "description-of-halt"},
3181     {  30, "device-address-binding"},
3182     {  31, "device-type"},
3183     {  32, "effective-period"},
3184     {  33, "elapsed-active-time"},
3185     {  34, "error-limit"},
3186     {  35, "event-enable"},
3187     {  36, "event-state"},
3188     {  37, "event-type"},
3189     {  38, "exception-schedule"},
3190     {  39, "fault-values"},
3191     {  40, "feedback-value"},
3192     {  41, "file-access-method"},
3193     {  42, "file-size"},
3194     {  43, "file-type"},
3195     {  44, "firmware-revision"},
3196     {  45, "high-limit"},
3197     {  46, "inactive-text"},
3198     {  47, "in-process"},
3199     {  48, "instance-of"},
3200     {  49, "integral-constant"},
3201     {  50, "integral-constant-units"},
3202     {  51, "issue-confirmed-notifications"},
3203     {  52, "limit-enable"},
3204     {  53, "list-of-group-members"},
3205     {  54, "list-of-object-property-references"},
3206     {  55, "list-of-session-keys"},
3207     {  56, "local-date"},
3208     {  57, "local-time"},
3209     {  58, "location"},
3210     {  59, "low-limit"},
3211     {  60, "manipulated-variable-reference"},
3212     {  61, "maximum-output"},
3213     {  62, "max-apdu-length-accepted"},
3214     {  63, "max-info-frames"},
3215     {  64, "max-master"},
3216     {  65, "max-pres-value"},
3217     {  66, "minimum-off-time"},
3218     {  67, "minimum-on-time"},
3219     {  68, "minimum-output"},
3220     {  69, "min-pres-value"},
3221     {  70, "model-name"},
3222     {  71, "modification-date"},
3223     {  72, "notify-type"},
3224     {  73, "number-of-APDU-retries"},
3225     {  74, "number-of-states"},
3226     {  75, "object-identifier"},
3227     {  76, "object-list"},
3228     {  77, "object-name"},
3229     {  78, "object-property-reference"},
3230     {  79, "object-type"},
3231     {  80, "optional"},
3232     {  81, "out-of-service"},
3233     {  82, "output-units"},
3234     {  83, "event-parameters"},
3235     {  84, "polarity"},
3236     {  85, "present-value"},
3237     {  86, "priority"},
3238     {  87, "priority-array"},
3239     {  88, "priority-for-writing"},
3240     {  89, "process-identifier"},
3241     {  90, "program-change"},
3242     {  91, "program-location"},
3243     {  92, "program-state"},
3244     {  93, "proportional-constant"},
3245     {  94, "proportional-constant-units"},
3246     {  95, "protocol-conformance-class"},
3247     {  96, "protocol-object-types-supported"},
3248     {  97, "protocol-services-supported"},
3249     {  98, "protocol-version"},
3250     {  99, "read-only"},
3251     { 100, "reason-for-halt"},
3252     { 101, "recipient"},
3253     { 102, "recipient-list"},
3254     { 103, "reliability"},
3255     { 104, "relinquish-default"},
3256     { 105, "required"},
3257     { 106, "resolution"},
3258     { 107, "segmentation-supported"},
3259     { 108, "setpoint"},
3260     { 109, "setpoint-reference"},
3261     { 110, "state-text"},
3262     { 111, "status-flags"},
3263     { 112, "system-status"},
3264     { 113, "time-delay"},
3265     { 114, "time-of-active-time-reset"},
3266     { 115, "time-of-state-count-reset"},
3267     { 116, "time-synchronization-recipients"},
3268     { 117, "units"},
3269     { 118, "update-interval"},
3270     { 119, "utc-offset"},
3271     { 120, "vendor-identifier"},
3272     { 121, "vendor-name"},
3273     { 122, "vt-class-supported"},
3274     { 123, "weekly-schedule"},
3275     { 124, "attempted-samples"},
3276     { 125, "average-value"},
3277     { 126, "buffer-size"},
3278     { 127, "client-cov-increment"},
3279     { 128, "cov-resubscription-interval"},
3280     { 129, "current-notify-time"},
3281     { 130, "event-time-stamp"},
3282     { 131, "log-buffer"},
3283     { 132, "log-device-object-property"},
3284     { 133, "enable"}, /* per ANSI/ASHRAE 135-2004 addendum B */
3285     { 134, "log-interval"},
3286     { 135, "maximum-value"},
3287     { 136, "minimum-value"},
3288     { 137, "notification-threshold"},
3289     { 138, "previous-notify-time"},
3290     { 139, "protocol-revision"},
3291     { 140, "records-since-notification"},
3292     { 141, "record-count"},
3293     { 142, "start-time"},
3294     { 143, "stop-time"},
3295     { 144, "stop-when-full"},
3296     { 145, "total-record-count"},
3297     { 146, "valid-samples"},
3298     { 147, "window-interval"},
3299     { 148, "window-samples"},
3300     { 149, "maximum-value-time-stamp"},
3301     { 150, "minimum-value-time-stamp"},
3302     { 151, "variance-value"},
3303     { 152, "active-cov-subscriptions"},
3304     { 153, "backup-failure-timeout"},
3305     { 154, "configuration-files"},
3306     { 155, "database-revision"},
3307     { 156, "direct-reading"},
3308     { 157, "last-restore-time"},
3309     { 158, "maintenance-required"},
3310     { 159, "member-of"},
3311     { 160, "mode"},
3312     { 161, "operation-expected"},
3313     { 162, "setting"},
3314     { 163, "silenced"},
3315     { 164, "tracking-value"},
3316     { 165, "zone-members"},
3317     { 166, "life-safety-alarm-values"},
3318     { 167, "max-segments-accepted"},
3319     { 168, "profile-name"},
3320     { 169, "auto-slave-discovery"},
3321     { 170, "manual-slave-address-binding"},
3322     { 171, "slave-address-binding"},
3323     { 172, "slave-proxy-enable"},
3324     { 173, "last-notify-record"},     /* bug 4117 */
3325     { 174, "schedule-default"},
3326     { 175, "accepted-modes"},
3327     { 176, "adjust-value"},
3328     { 177, "count"},
3329     { 178, "count-before-change"},
3330     { 179, "count-change-time"},
3331     { 180, "cov-period"},
3332     { 181, "input-reference"},
3333     { 182, "limit-monitoring-interval"},
3334     { 183, "logging-device"},
3335     { 184, "logging-record"},
3336     { 185, "prescale"},
3337     { 186, "pulse-rate"},
3338     { 187, "scale"},
3339     { 188, "scale-factor"},
3340     { 189, "update-time"},
3341     { 190, "value-before-change"},
3342     { 191, "value-set"},
3343     { 192, "value-change-time"},
3344     { 193, "align-intervals"},
3345     { 194, "group-member-names"},
3346     { 195, "interval-offset"},
3347     { 196, "last-restart-reason"},
3348     { 197, "logging-type"},
3349     { 198, "member-status-flags"},
3350     { 199, "notification-period"},
3351     { 200, "previous-notify-record"},
3352     { 201, "requested-update-interval"},
3353     { 202, "restart-notification-recipients"},
3354     { 203, "time-of-device-restart"},
3355     { 204, "time-synchronization-interval"},
3356     { 205, "trigger"},
3357     { 206, "UTC-time-synchronization-recipients"},
3358     { 207, "node-subtype"},
3359     { 208, "node-type"},
3360     { 209, "structured-object-list"},
3361     { 210, "subordinate-annotations"},
3362     { 211, "subordinate-list"},
3363     { 212, "actual-shed-level"},
3364     { 213, "duty-window"},
3365     { 214, "expected-shed-level"},
3366     { 215, "full-duty-baseline"},
3367     { 216, "node-subtype"},
3368     { 217, "node-type"},
3369     { 218, "requested-shed-level"},
3370     { 219, "shed-duration"},
3371     { 220, "shed-level-descriptions"},
3372     { 221, "shed-levels"},
3373     { 222, "state-description"},
3374     /* enumeration values 223-225 are unassigned */
3375     { 226, "door-alarm-state"},
3376     { 227, "door-extended-pulse-time"},
3377     { 228, "door-members"},
3378     { 229, "door-open-too-long-time"},
3379     { 230, "door-pulse-time"},
3380     { 231, "door-status"},
3381     { 232, "door-unlock-delay-time"},
3382     { 233, "lock-status"},
3383     { 234, "masked-alarm-values"},
3384     { 235, "secured-status"},
3385     /* enumeration values 236-243 are unassigned */
3386     { 244, "absentee-limit"},     /* added with addenda 135-2008j */
3387     { 245, "access-alarm-events"},
3388     { 246, "access-doors"},
3389     { 247, "access-event"},
3390     { 248, "access-event-authentication-factor"},
3391     { 249, "access-event-credential"},
3392     { 250, "access-event-time"},
3393     { 251, "access-transaction-events"},
3394     { 252, "accompaniment"},
3395     { 253, "accompaniment-time"},
3396     { 254, "activation-time"},
3397     { 255, "active-authentication-policy"},
3398     { 256, "assigned-access-rights"},
3399     { 257, "authentication-factors"},
3400     { 258, "authentication-policy-list"},
3401     { 259, "authentication-policy-names"},
3402     { 260, "authentication-status"},
3403     { 261, "authorization-mode"},
3404     { 262, "belongs-to"},
3405     { 263, "credential-disable"},
3406     { 264, "credential-status"},
3407     { 265, "credentials"},
3408     { 266, "credentials-in-zone"},
3409     { 267, "days-remaining"},
3410     { 268, "entry-points"},
3411     { 269, "exit-points"},
3412     { 270, "expiry-time"},
3413     { 271, "extended-time-enable"},
3414     { 272, "failed-attempt-events"},
3415     { 273, "failed-attempts"},
3416     { 274, "failed-attempts-time"},
3417     { 275, "last-access-event"},
3418     { 276, "last-access-point"},
3419     { 277, "last-credential-added"},
3420     { 278, "last-credential-added-time"},
3421     { 279, "last-credential-removed"},
3422     { 280, "last-credential-removed-time"},
3423     { 281, "last-use-time"},
3424     { 282, "lockout"},
3425     { 283, "lockout-relinquish-time"},
3426     { 284, "master-exemption"},
3427     { 285, "max-failed-attempts"},
3428     { 286, "members"},
3429     { 287, "muster-point"},
3430     { 288, "negative-access-rules"},
3431     { 289, "number-of-authentication-policies"},
3432     { 290, "occupancy-count"},
3433     { 291, "occupancy-count-adjust"},
3434     { 292, "occupancy-count-enable"},
3435     { 293, "occupancy-exemption"},
3436     { 294, "occupancy-lower-limit"},
3437     { 295, "occupancy-lower-limit-enforced"},
3438     { 296, "occupancy-state"},
3439     { 297, "occupancy-upper-limit"},
3440     { 298, "occupancy-upper-limit-enforced"},
3441     { 299, "passback-exemption"},
3442     { 300, "passback-mode"},
3443     { 301, "passback-timeout"},
3444     { 302, "positive-access-rules"},
3445     { 303, "reason-for-disable"},
3446     { 304, "supported-formats"},
3447     { 305, "supported-format-classes"},
3448     { 306, "threat-authority"},
3449     { 307, "threat-level"},
3450     { 308, "trace-flag"},
3451     { 309, "transaction-notification-class"},
3452     { 310, "user-external-identifier"},
3453     { 311, "user-information-reference"},
3454     /* enumeration values 312-316 are unassigned */
3455     { 317, "user-name"},
3456     { 318, "user-type"},
3457     { 319, "uses-remaining"},
3458     { 320, "zone-from"},
3459     { 321, "zone-to"},
3460     { 322, "access-event-tag"},
3461     { 323, "global-identifier"},
3462     /* enumeration values 324-325 reserved for future addenda */
3463     { 326, "verification-time"},
3464     { 327, "base-device-security-policy"},
3465     { 328, "distribution-key-revision"},
3466     { 329, "do-not-hide"},
3467     { 330, "key-sets"},
3468     { 331, "last-key-server"},
3469     { 332, "network-access-security-policies"},
3470     { 333, "packet-reorder-time"},
3471     { 334, "security-pdu-timeout"},
3472     { 335, "security-time-window"},
3473     { 336, "supported-security-algorithms"},
3474     { 337, "update-key-set-timeout"},
3475     { 338, "backup-and-restore-state"},
3476     { 339, "backup-preparation-time"},
3477     { 340, "restore-completion-time"},
3478     { 341, "restore-preparation-time"},
3479     { 342, "bit-mask"},       /* addenda 135-2008w */
3480     { 343, "bit-text"},
3481     { 344, "is-utc"},
3482     { 345, "group-members"},
3483     { 346, "group-member-names"},
3484     { 347, "member-status-flags"},
3485     { 348, "requested-update-interval"},
3486     { 349, "covu-period"},
3487     { 350, "covu-recipients"},
3488     { 351, "event-message-texts"},
3489     { 0,   NULL}
3490 /* Enumerated values 0-511 are reserved for definition by ASHRAE.
3491    Enumerated values 512-4194303 may be used by others subject to
3492    the procedures and constraints described in Clause 23. */
3493 };
3494
3495 static const value_string
3496 BACnetBinaryPV [] = {
3497     { 0, "inactive"},
3498     { 1, "active"},
3499     { 0, NULL}
3500 };
3501
3502
3503 #define ANSI_X3_4      0 /* ANSI X3.4, a/k/a "ASCII"; full UTF-8 since 2010 */
3504                          /* See, for example, ANSI/ASHRAE Addendum k to ANSI/ASHRAE Standard 135-2008 */
3505                          /* XXX - I've seen captures using this for ISO 8859-1 */
3506 #define IBM_MS_DBCS    1 /* "IBM/Microsoft DBCS"; was there only one such DBCS? */
3507 #define JIS_C_6226     2 /* JIS C 6226 */
3508 #define ISO_10646_UCS4 3 /* ISO 10646 (UCS-4) - 4-byte Unicode */
3509 #define ISO_10646_UCS2 4 /* ISO 10646 (UCS-2) - 2-byte Unicode Basic Multilingual Plane (not UTF-16, presumably) */
3510 #define ISO_8859_1     5 /* ISO 8859-1 */
3511 static const value_string
3512 BACnetCharacterSet [] = {
3513     { ANSI_X3_4,      "ANSI X3.4 / UTF-8 (since 2010)"},
3514     { IBM_MS_DBCS,    "IBM/Microsoft DBCS"},
3515     { JIS_C_6226,     "JIS C 6226"},
3516     { ISO_10646_UCS4, "ISO 10646 (UCS-4)"},
3517     { ISO_10646_UCS2, "ISO 10646 (UCS-2)"},
3518     { ISO_8859_1,     "ISO 8859-1"},
3519     { 0,     NULL}
3520 };
3521
3522 static const value_string
3523 BACnetStatusFlags [] = {
3524     { 0, "in-alarm"},
3525     { 1, "fault"},
3526     { 2, "overridden"},
3527     { 3, "out-of-service"},
3528     { 0, NULL}
3529 };
3530
3531 static const value_string
3532 BACnetMessagePriority [] = {
3533     { 0, "normal"},
3534     { 1, "urgent"},
3535     { 0, NULL}
3536 };
3537
3538 static const value_string
3539 BACnetAcknowledgementFilter [] = {
3540     { 0, "all"},
3541     { 1, "acked"},
3542     { 2, "not-acked"},
3543     { 0, NULL}
3544 };
3545
3546 static const value_string
3547 BACnetResultFlags [] = {
3548     { 0, "firstitem"},
3549     { 1, "lastitem"},
3550     { 2, "moreitems"},
3551     { 0, NULL}
3552 };
3553
3554 static const value_string
3555 BACnetRelationSpecifier [] = {
3556     { 0, "equal"},
3557     { 1, "not-equal"},
3558     { 2, "less-than"},
3559     { 3, "greater-than"},
3560     { 4, "less-than-or-equal"},
3561     { 5, "greater-than-or-equal"},
3562     { 0, NULL}
3563 };
3564
3565 static const value_string
3566 BACnetSelectionLogic [] = {
3567     { 0, "and"},
3568     { 1, "or"},
3569     { 2, "all"},
3570     { 0, NULL}
3571 };
3572
3573 static const value_string
3574 BACnetEventStateFilter [] = {
3575     { 0, "offnormal"},
3576     { 1, "fault"},
3577     { 2, "normal"},
3578     { 3, "all"},
3579     { 4, "active"},
3580     { 0, NULL}
3581 };
3582
3583 static const value_string
3584 BACnetEventTransitionBits [] = {
3585     { 0, "to-offnormal"},
3586     { 1, "to-fault"},
3587     { 2, "to-normal"},
3588     { 0, NULL}
3589 };
3590
3591 static const value_string
3592 BACnetSegmentation [] = {
3593     { 0, "segmented-both"},
3594     { 1, "segmented-transmit"},
3595     { 2, "segmented-receive"},
3596     { 3, "no-segmentation"},
3597     { 0, NULL}
3598 };
3599
3600 static const value_string
3601 BACnetSilencedState [] = {
3602     { 0, "unsilenced"},
3603     { 1, "audible-silenced"},
3604     { 2, "visible-silenced"},
3605     { 3, "all-silenced"},
3606     { 0, NULL}
3607 };
3608
3609 static const value_string
3610 BACnetDeviceStatus [] = {
3611     { 0, "operational"},
3612     { 1, "operational-read-only"},
3613     { 2, "download-required"},
3614     { 3, "download-in-progress"},
3615     { 4, "non-operational"},
3616     { 5, "backup-in-progress"},
3617     { 0, NULL}
3618 };
3619
3620 static const value_string
3621 BACnetEnableDisable [] = {
3622     { 0, "enable"},
3623     { 1, "disable"},
3624     { 2, "disable-initiation"},
3625     { 0, NULL}
3626 };
3627
3628 static const value_string
3629 months [] = {
3630     {   1, "January" },
3631     {   2, "February" },
3632     {   3, "March" },
3633     {   4, "April" },
3634     {   5, "May" },
3635     {   6, "June" },
3636     {   7, "July" },
3637     {   8, "August" },
3638     {   9, "September" },
3639     {  10, "October" },
3640     {  11, "November" },
3641     {  12, "December" },
3642     { 255, "any month" },
3643     { 0,   NULL }
3644 };
3645
3646 static const value_string
3647 weekofmonth [] = {
3648     {   1, "days numbered 1-7" },
3649     {   2, "days numbered 8-14" },
3650     {   3, "days numbered 15-21" },
3651     {   4, "days numbered 22-28" },
3652     {   5, "days numbered 29-31" },
3653     {   6, "last 7 days of this month" },
3654     { 255, "any week of this month" },
3655     { 0,   NULL }
3656 };
3657
3658 /* note: notification class object recipient-list uses
3659    different day-of-week enum */
3660 static const value_string
3661 day_of_week [] = {
3662     {   1, "Monday" },
3663     {   2, "Tuesday" },
3664     {   3, "Wednesday" },
3665     {   4, "Thursday" },
3666     {   5, "Friday" },
3667     {   6, "Saturday" },
3668     {   7, "Sunday" },
3669     { 255, "any day of week" },
3670     { 0,   NULL }
3671 };
3672
3673 static const value_string
3674 BACnetErrorClass [] = {
3675     { 0, "device" },
3676     { 1, "object" },
3677     { 2, "property" },
3678     { 3, "resources" },
3679     { 4, "security" },
3680     { 5, "services" },
3681     { 6, "vt" },
3682     { 7, "communication" },
3683     { 0, NULL }
3684 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3685    Enumerated values64-65535 may be used by others subject to
3686    the procedures and constraints described in Clause 23. */
3687 };
3688
3689 static const value_string
3690 BACnetVTClass [] = {
3691     { 0, "default-terminal" },
3692     { 1, "ansi-x3-64" },
3693     { 2, "dec-vt52" },
3694     { 3, "dec-vt100" },
3695     { 4, "dec-vt200" },
3696     { 5, "hp-700-94" },
3697     { 6, "ibm-3130" },
3698     { 0, NULL }
3699 };
3700
3701 static const value_string
3702 BACnetEventType [] = {
3703     {  0, "change-of-bitstring" },
3704     {  1, "change-of-state" },
3705     {  2, "change-of-value" },
3706     {  3, "command-failure" },
3707     {  4, "floating-limit" },
3708     {  5, "out-of-range" },
3709     {  6, "complex-event-type" },
3710     {  7, "(deprecated)buffer-ready" },
3711     {  8, "change-of-life-safety" },
3712     {  9, "extended" },
3713     { 10, "buffer-ready" },
3714     { 11, "unsigned-range" },
3715     { 14, "double-out-of-range"},     /* added with addenda 135-2008w */
3716     { 15, "signed-out-of-range"},
3717     { 16, "unsigned-out-of-range"},
3718     { 17, "change-of-characterstring"},
3719     { 18, "change-of-status-flags"},
3720     { 0,  NULL }
3721 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3722    Enumerated values 64-65535 may be used by others subject to
3723    the procedures and constraints described in Clause 23.
3724    It is expected that these enumerated values will correspond
3725    to the use of the complex-event-type CHOICE [6] of the
3726    BACnetNotificationParameters production. */
3727 };
3728
3729 static const value_string
3730 BACnetEventState [] = {
3731     { 0, "normal" },
3732     { 1, "fault" },
3733     { 2, "offnormal" },
3734     { 3, "high-limit" },
3735     { 4, "low-limit" },
3736     { 5, "life-safety-alarm" },
3737     { 0, NULL }
3738 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3739    Enumerated values 64-65535 may be used by others subject to
3740    the procedures and constraints described in Clause 23.  */
3741 };
3742
3743 static const value_string
3744 BACnetLogStatus [] = {
3745     { 0, "log-disabled" },
3746     { 1, "buffer-purged" },
3747     { 2, "log-interrupted"},
3748     { 0, NULL }
3749 };
3750
3751 static const value_string
3752 BACnetMaintenance [] = {
3753     { 0, "none" },
3754     { 1, "periodic-test" },
3755     { 2, "need-service-operational" },
3756     { 3, "need-service-inoperative" },
3757     { 0, NULL }
3758 };
3759
3760 static const value_string
3761 BACnetNotifyType [] = {
3762     { 0, "alarm" },
3763     { 1, "event" },
3764     { 2, "ack-notification" },
3765     { 0, NULL }
3766 };
3767
3768 static const value_string
3769 BACnetServicesSupported [] = {
3770     {  0, "acknowledgeAlarm"},
3771     {  1, "confirmedCOVNotification"},
3772     {  2, "confirmedEventNotification"},
3773     {  3, "getAlarmSummary"},
3774     {  4, "getEnrollmentSummary"},
3775     {  5, "subscribeCOV"},
3776     {  6, "atomicReadFile"},
3777     {  7, "atomicWriteFile"},
3778     {  8, "addListElement"},
3779     {  9, "removeListElement"},
3780     { 10, "createObject"},
3781     { 11, "deleteObject"},
3782     { 12, "readProperty"},
3783     { 13, "readPropertyConditional"},
3784     { 14, "readPropertyMultiple"},
3785     { 15, "writeProperty"},
3786     { 16, "writePropertyMultiple"},
3787     { 17, "deviceCommunicationControl"},
3788     { 18, "confirmedPrivateTransfer"},
3789     { 19, "confirmedTextMessage"},
3790     { 20, "reinitializeDevice"},
3791     { 21, "vtOpen"},
3792     { 22, "vtClose"},
3793     { 23, "vtData"},
3794     { 24, "authenticate"},
3795     { 25, "requestKey"},
3796     { 26, "i-Am"},
3797     { 27, "i-Have"},
3798     { 28, "unconfirmedCOVNotification"},
3799     { 29, "unconfirmedEventNotification"},
3800     { 30, "unconfirmedPrivateTransfer"},
3801     { 31, "unconfirmedTextMessage"},
3802     { 32, "timeSynchronization"},
3803     { 33, "who-Has"},
3804     { 34, "who-Is"},
3805     { 35, "readRange"},
3806     { 36, "utcTimeSynchronization"},
3807     { 37, "lifeSafetyOperation"},
3808     { 38, "subscribeCOVProperty"},
3809     { 39, "getEventInformation"},
3810     { 0,  NULL}
3811 };
3812
3813 static const value_string
3814 BACnetPropertyStates [] = {
3815     {  0, "boolean-value"},
3816     {  1, "binary-value"},
3817     {  2, "event-type"},
3818     {  3, "polarity"},
3819     {  4, "program-change"},
3820     {  5, "program-state"},
3821     {  6, "reason-for-halt"},
3822     {  7, "reliability"},
3823     {  8, "state"},
3824     {  9, "system-status"},
3825     { 10, "units"},
3826     { 11, "unsigned-value"},
3827     { 12, "life-safety-mode"},
3828     { 13, "life-safety-state"},
3829     { 14, "restart-reason"},
3830     { 15, "door-alarm-state"},
3831     { 16, "action"},
3832     { 17, "door-secured-status"},
3833     { 18, "door-status"},
3834     { 19, "door-value"},
3835     { 20, "file-access-method"},
3836     { 21, "lock-status"},
3837     { 22, "life-safety-operation"},
3838     { 23, "maintenance"},
3839     { 24, "node-type"},
3840     { 25, "notify-type"},
3841     { 26, "security-level"},
3842     { 27, "shed-state"},
3843     { 28, "silenced-state"},
3844     /* context tag 29 reserved for future addenda */
3845     { 29, "unknown-29"},
3846     { 30, "access-event"},
3847     { 31, "zone-occupancy-state"},
3848     { 32, "access-credential-disable-reason"},
3849     { 33, "access-credential-disable"},
3850     { 34, "authentication-status"},
3851     { 35, "unknown-35"},
3852     { 36, "backup-state"},
3853     { 0, NULL}
3854 /* Tag values 0-63 are reserved for definition by ASHRAE.
3855    Tag values of 64-254 may be used by others to accommodate
3856    vendor specific properties that have discrete or enumerated values,
3857    subject to the constraints described in Clause 23. */
3858 };
3859
3860 static const value_string
3861 BACnetProgramError [] = {
3862     { 0, "normal"},
3863     { 1, "load-failed"},
3864     { 2, "internal"},
3865     { 3, "program"},
3866     { 4, "other"},
3867     { 0, NULL}
3868 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3869    Enumerated values 64-65535 may be used by others subject to
3870    the procedures and constraints described in Clause 23. */
3871 };
3872
3873 static const value_string
3874 BACnetProgramRequest [] = {
3875     { 0, "ready"},
3876     { 1, "load"},
3877     { 2, "run"},
3878     { 3, "halt"},
3879     { 4, "restart"},
3880     { 4, "unload"},
3881     { 0, NULL}
3882 };
3883
3884 static const value_string
3885 BACnetProgramState [] = {
3886     { 0, "idle"},
3887     { 1, "loading"},
3888     { 2, "running"},
3889     { 3, "waiting"},
3890     { 4, "halted"},
3891     { 4, "unloading"},
3892     { 0, NULL}
3893 };
3894
3895 static const value_string
3896 BACnetReinitializedStateOfDevice [] = {
3897     { 0, "coldstart"},
3898     { 1, "warmstart"},
3899     { 2, "startbackup"},
3900     { 3, "endbackup"},
3901     { 4, "startrestore"},
3902     { 5, "endrestore"},
3903     { 6, "abortrestore"},
3904     { 0, NULL}
3905 };
3906
3907 static const value_string
3908 BACnetPolarity [] = {
3909     { 0, "normal"},
3910     { 1, "reverse"},
3911     { 0, NULL}
3912 };
3913
3914 static const value_string
3915 BACnetTagNames[] = {
3916     { 5, "Extended Value" },
3917     { 6, "Opening Tag" },
3918     { 7, "Closing Tag" },
3919     { 0, NULL }
3920 };
3921
3922 static const value_string
3923 BACnetReadRangeOptions[] = {
3924     { 3, "range byPosition" },
3925     { 4, "range byTime" },
3926     { 5, "range timeRange" },
3927     { 6, "range bySequenceNumber" },
3928     { 7, "range byTime" },
3929     { 0, NULL }
3930 };
3931
3932 /* Present_Value for Load Control Object */
3933 static const value_string
3934 BACnetShedState[] = {
3935     { 0, "shed-inactive" },
3936     { 1, "shed-request-pending" },
3937     { 2, "shed-compliant" },
3938     { 3, "shed-non-compliant" },
3939     { 0, NULL }
3940 };
3941
3942 static const value_string
3943 BACnetNodeType [] = {
3944     { 0, "unknown" },
3945     { 1, "system" },
3946     { 2, "network" },
3947     { 3, "device" },
3948     { 4, "organizational" },
3949     { 5, "area" },
3950     { 6, "equipment" },
3951     { 7, "point" },
3952     { 8, "collection" },
3953     { 9, "property" },
3954     { 10, "functional" },
3955     { 11, "other" },
3956     { 0, NULL }
3957 };
3958
3959 static const value_string
3960 BACnetLoggingType [] = {
3961     { 0, "polled" },
3962     { 1, "cov" },
3963     { 2, "triggered" },
3964     { 0, NULL }
3965 };
3966
3967 static const value_string
3968 BACnetDoorStatus [] = {
3969     { 0, "closed" },
3970     { 1, "opened" },
3971     { 2, "unknown" },
3972     { 0, NULL }
3973 };
3974
3975 static const value_string
3976 BACnetLockStatus [] = {
3977     { 0, "locked" },
3978     { 1, "unlocked" },
3979     { 2, "fault" },
3980     { 3, "unknown" },
3981     { 0, NULL }
3982 };
3983
3984 static const value_string
3985 BACnetDoorSecuredStatus [] = {
3986     { 0, "secured" },
3987     { 1, "unsecured" },
3988     { 2, "unknown" },
3989     { 0, NULL }
3990 };
3991
3992 static const value_string
3993 BACnetDoorAlarmState [] = {
3994     { 0, "normal" },
3995     { 1, "alarm" },
3996     { 2, "door-open-too-long" },
3997     { 3, "forced-open" },
3998     { 4, "tamper" },
3999     { 5, "door-fault" },
4000     { 6, "lock-down" },
4001     { 7, "free-access" },
4002     { 8, "egress-open" },
4003     { 0, NULL }
4004 };
4005
4006 static const value_string
4007 BACnetAccumulatorStatus [] = {
4008     { 0, "normal" },
4009     { 1, "starting" },
4010     { 2, "recovered" },
4011     { 3, "abnormal" },
4012     { 4, "failed" },
4013     { 0, NULL }
4014 };
4015
4016 /* These values are (manually) transferred from
4017  * http://www.bacnet.org/VendorID/BACnet Vendor IDs.htm
4018  * Version: "As of September 16, 2013"
4019  */
4020
4021 static const value_string
4022 BACnetVendorIdentifiers [] = {
4023     {   0, "ASHRAE" },
4024     {   1, "NIST" },
4025     {   2, "The Trane Company" },
4026     {   3, "McQuay International" },
4027     {   4, "PolarSoft" },
4028     {   5, "Johnson Controls, Inc." },
4029     {   6, "American Auto-Matrix" },
4030     {   7, "Siemens Schweiz AG (Formerly: Landis & Staefa Division Europe)" },
4031     {   8, "Delta Controls" },
4032     {   9, "Siemens Schweiz AG" },
4033     {  10, "Schneider Electric" },
4034     {  11, "TAC" },
4035     {  12, "Orion Analysis Corporation" },
4036     {  13, "Teletrol Systems Inc." },
4037     {  14, "Cimetrics Technology" },
4038     {  15, "Cornell University" },
4039     {  16, "United Technologies Carrier" },
4040     {  17, "Honeywell Inc." },
4041     {  18, "Alerton / Honeywell" },
4042     {  19, "TAC AB" },
4043     {  20, "Hewlett-Packard Company" },
4044     {  21, "Dorsette's Inc." },
4045     {  22, "Siemens Schweiz AG (Formerly: Cerberus AG)" },
4046     {  23, "York Controls Group" },
4047     {  24, "Automated Logic Corporation" },
4048     {  25, "CSI Control Systems International" },
4049     {  26, "Phoenix Controls Corporation" },
4050     {  27, "Innovex Technologies, Inc." },
4051     {  28, "KMC Controls, Inc." },
4052     {  29, "Xn Technologies, Inc." },
4053     {  30, "Hyundai Information Technology Co., Ltd." },
4054     {  31, "Tokimec Inc." },
4055     {  32, "Simplex" },
4056     {  33, "North Building Technologies Limited" },
4057     {  34, "Notifier" },
4058     {  35, "Reliable Controls Corporation" },
4059     {  36, "Tridium Inc." },
4060     {  37, "Sierra Monitor Corporation/FieldServer Technologies" },
4061     {  38, "Silicon Energy" },
4062     {  39, "Kieback & Peter GmbH & Co KG" },
4063     {  40, "Anacon Systems, Inc." },
4064     {  41, "Systems Controls & Instruments, LLC" },
4065     {  42, "Lithonia Lighting" },
4066     {  43, "Micropower Manufacturing" },
4067     {  44, "Matrix Controls" },
4068     {  45, "METALAIRE" },
4069     {  46, "ESS Engineering" },
4070     {  47, "Sphere Systems Pty Ltd." },
4071     {  48, "Walker Technologies Corporation" },
4072     {  49, "H I Solutions, Inc." },
4073     {  50, "MBS GmbH" },
4074     {  51, "SAMSON AG" },
4075     {  52, "Badger Meter Inc." },
4076     {  53, "DAIKIN Industries Ltd." },
4077     {  54, "NARA Controls Inc." },
4078     {  55, "Mammoth Inc." },
4079     {  56, "Liebert Corporation" },
4080     {  57, "SEMCO Incorporated" },
4081     {  58, "Air Monitor Corporation" },
4082     {  59, "TRIATEK, LLC" },
4083     {  60, "NexLight" },
4084     {  61, "Multistack" },
4085     {  62, "TSI Incorporated" },
4086     {  63, "Weather-Rite, Inc." },
4087     {  64, "Dunham-Bush" },
4088     {  65, "Reliance Electric" },
4089     {  66, "LCS Inc." },
4090     {  67, "Regulator Australia PTY Ltd." },
4091     {  68, "Touch-Plate Lighting Controls" },
4092     {  69, "Amann GmbH" },
4093     {  70, "RLE Technologies" },
4094     {  71, "Cardkey Systems" },
4095     {  72, "SECOM Co., Ltd." },
4096     {  73, "ABB Gebaeudetechnik AG Bereich NetServ" },
4097     {  74, "KNX Association cvba" },
4098     {  75, "Institute of Electrical Installation Engineers of Japan (IEIEJ)" },
4099     {  76, "Nohmi Bosai, Ltd." },
4100     {  77, "Carel S.p.A." },
4101     {  78, "UTC Fire & Security Espana, S.L." },
4102     {  79, "Hochiki Corporation" },
4103     {  80, "Fr. Sauter AG" },
4104     {  81, "Matsushita Electric Works, Ltd." },
4105     {  82, "Mitsubishi Electric Corporation, Inazawa Works" },
4106     {  83, "Mitsubishi Heavy Industries, Ltd." },
4107     {  84, "ITT Bell & Gossett" },
4108     {  85, "Yamatake Building Systems Co., Ltd." },
4109     {  86, "The Watt Stopper, Inc." },
4110     {  87, "Aichi Tokei Denki Co., Ltd." },
4111     {  88, "Activation Technologies, LLC" },
4112     {  89, "Saia-Burgess Controls, Ltd." },
4113     {  90, "Hitachi, Ltd." },
4114     {  91, "Novar Corp./Trend Control Systems Ltd." },
4115     {  92, "Mitsubishi Electric Lighting Corporation" },
4116     {  93, "Argus Control Systems, Ltd." },
4117     {  94, "Kyuki Corporation" },
4118     {  95, "Richards-Zeta Building Intelligence, Inc." },
4119     {  96, "Scientech R&D, Inc." },
4120     {  97, "VCI Controls, Inc." },
4121     {  98, "Toshiba Corporation" },
4122     {  99, "Mitsubishi Electric Corporation Air Conditioning & Refrigeration Systems Works" },
4123     { 100, "Custom Mechanical Equipment, LLC" },
4124     { 101, "ClimateMaster" },
4125     { 102, "ICP Panel-Tec, Inc." },
4126     { 103, "D-Tek Controls" },
4127     { 104, "NEC Engineering, Ltd." },
4128     { 105, "PRIVA BV" },
4129     { 106, "Meidensha Corporation" },
4130     { 107, "JCI Systems Integration Services" },
4131     { 108, "Freedom Corporation" },
4132     { 109, "Neuberger Gebaeudeautomation GmbH" },
4133     { 110, "Sitronix" },
4134     { 111, "Leviton Manufacturing" },
4135     { 112, "Fujitsu Limited" },
4136     { 113, "Emerson Network Power" },
4137     { 114, "S. A. Armstrong, Ltd." },
4138     { 115, "Visonet AG" },
4139     { 116, "M&M Systems, Inc." },
4140     { 117, "Custom Software Engineering" },
4141     { 118, "Nittan Company, Limited" },
4142     { 119, "Elutions Inc. (Wizcon Systems SAS)" },
4143     { 120, "Pacom Systems Pty., Ltd." },
4144     { 121, "Unico, Inc." },
4145     { 122, "Ebtron, Inc." },
4146     { 123, "Scada Engine" },
4147     { 124, "AC Technology Corporation" },
4148     { 125, "Eagle Technology" },
4149     { 126, "Data Aire, Inc." },
4150     { 127, "ABB, Inc." },
4151     { 128, "Transbit Sp. z o. o." },
4152     { 129, "Toshiba Carrier Corporation" },
4153     { 130, "Shenzhen Junzhi Hi-Tech Co., Ltd." },
4154     { 131, "Tokai Soft" },
4155     { 132, "Blue Ridge Technologies" },
4156     { 133, "Veris Industries" },
4157     { 134, "Centaurus Prime" },
4158     { 135, "Sand Network Systems" },
4159     { 136, "Regulvar, Inc." },
4160     { 137, "AFDtek Division of Fastek International Inc." },
4161     { 138, "PowerCold Comfort Air Solutions, Inc." },
4162     { 139, "I Controls" },
4163     { 140, "Viconics Electronics, Inc." },
4164     { 141, "Yaskawa America, Inc." },
4165     { 142, "DEOS control systems GmbH" },
4166     { 143, "Digitale Mess- und Steuersysteme AG" },
4167     { 144, "Fujitsu General Limited" },
4168     { 145, "Project Engineering S.r.l." },
4169     { 146, "Sanyo Electric Co., Ltd." },
4170     { 147, "Integrated Information Systems, Inc." },
4171     { 148, "Temco Controls, Ltd." },
4172     { 149, "Airtek International Inc." },
4173     { 150, "Advantech Corporation" },
4174     { 151, "Titan Products, Ltd." },
4175     { 152, "Regel Partners" },
4176     { 153, "National Environmental Product" },
4177     { 154, "Unitec Corporation" },
4178     { 155, "Kanden Engineering Company" },
4179     { 156, "Messner Gebaeudetechnik GmbH" },
4180     { 157, "Integrated.CH" },
4181     { 158, "Price Industries" },
4182     { 159, "SE-Elektronic GmbH" },
4183     { 160, "Rockwell Automation" },
4184     { 161, "Enflex Corp." },
4185     { 162, "ASI Controls" },
4186     { 163, "SysMik GmbH Dresden" },
4187     { 164, "HSC Regelungstechnik GmbH" },
4188     { 165, "Smart Temp Australia Pty.  Ltd." },
4189     { 166, "Cooper Controls" },
4190     { 167, "Duksan Mecasys Co., Ltd." },
4191     { 168, "Fuji IT Co., Ltd." },
4192     { 169, "Vacon Plc" },
4193     { 170, "Leader Controls" },
4194     { 171, "Cylon Controls, Ltd." },
4195     { 172, "Compas" },
4196     { 173, "Mitsubishi Electric Building Techno-Service Co., Ltd." },
4197     { 174, "Building Control Integrators" },
4198     { 175, "ITG Worldwide (M) Sdn Bhd" },
4199     { 176, "Lutron Electronics Co., Inc." },
4200     { 177, "Cooper-Atkins Corporation" },
4201     { 178, "LOYTEC Electronics GmbH" },
4202     { 179, "ProLon" },
4203     { 180, "Mega Controls Limited" },
4204     { 181, "Micro Control Systems, Inc." },
4205     { 182, "Kiyon, Inc." },
4206     { 183, "Dust Networks" },
4207     { 184, "Advanced Building Automation Systems" },
4208     { 185, "Hermos AG" },
4209     { 186, "CEZIM" },
4210     { 187, "Softing" },
4211     { 188, "Lynxspring, Inc." },
4212     { 189, "Schneider Toshiba Inverter Europe" },
4213     { 190, "Danfoss Drives A/S" },
4214     { 191, "Eaton Corporation" },
4215     { 192, "Matyca S.A." },
4216     { 193, "Botech AB" },
4217     { 194, "Noveo, Inc." },
4218     { 195, "AMEV" },
4219     { 196, "Yokogawa Electric Corporation" },
4220     { 197, "GFR Gesellschaft fuer Regelungstechnik" },
4221     { 198, "Exact Logic" },
4222     { 199, "Mass Electronics Pty Ltd dba Innotech Control Systems Australia" },
4223     { 200, "Kandenko Co., Ltd." },
4224     { 201, "DTF, Daten-Technik Fries" },
4225     { 202, "Klimasoft, Ltd." },
4226     { 203, "Toshiba Schneider Inverter Corporation" },
4227     { 204, "Control Applications, Ltd." },
4228     { 205, "KDT Systems Co., Ltd." },
4229     { 206, "Onicon Incorporated" },
4230     { 207, "Automation Displays, Inc." },
4231     { 208, "Control Solutions, Inc." },
4232     { 209, "Remsdaq Limited" },
4233     { 210, "NTT Facilities, Inc." },
4234     { 211, "VIPA GmbH" },
4235     { 212, "TSC21 Association of Japan" },
4236     { 213, "Strato Automation" },
4237     { 214, "HRW Limited" },
4238     { 215, "Lighting Control & Design, Inc." },
4239     { 216, "Mercy Electronic and Electrical Industries" },
4240     { 217, "Samsung SDS Co., Ltd" },
4241     { 218, "Impact Facility Solutions, Inc." },
4242     { 219, "Aircuity" },
4243     { 220, "Control Techniques, Ltd." },
4244     { 221, "OpenGeneral Pty., Ltd." },
4245     { 222, "WAGO Kontakttechnik GmbH & Co. KG" },
4246     { 223, "Cerus Industrial" },
4247     { 224, "Chloride Power Protection Company" },
4248     { 225, "Computrols, Inc." },
4249     { 226, "Phoenix Contact GmbH & Co. KG" },
4250     { 227, "Grundfos Management A/S" },
4251     { 228, "Ridder Drive Systems" },
4252     { 229, "Soft Device SDN BHD" },
4253     { 230, "Integrated Control Technology Limited" },
4254     { 231, "AIRxpert Systems, Inc." },
4255     { 232, "Microtrol Limited" },
4256     { 233, "Red Lion Controls" },
4257     { 234, "Digital Electronics Corporation" },
4258     { 235, "Ennovatis GmbH" },
4259     { 236, "Serotonin Software Technologies, Inc." },
4260     { 237, "LS Industrial Systems Co., Ltd." },
4261     { 238, "Square D Company" },
4262     { 239, "S Squared Innovations, Inc." },
4263     { 240, "Aricent Ltd." },
4264     { 241, "EtherMetrics, LLC" },
4265     { 242, "Industrial Control Communications, Inc." },
4266     { 243, "Paragon Controls, Inc." },
4267     { 244, "A. O. Smith Corporation" },
4268     { 245, "Contemporary Control Systems, Inc." },
4269     { 246, "Intesis Software SL" },
4270     { 247, "Ingenieurgesellschaft N. Hartleb mbH" },
4271     { 248, "Heat-Timer Corporation" },
4272     { 249, "Ingrasys Technology, Inc." },
4273     { 250, "Costerm Building Automation" },
4274     { 251, "WILO SE" },
4275     { 252, "Embedia Technologies Corp." },
4276     { 253, "Technilog" },
4277     { 254, "HR Controls Ltd. & Co. KG" },
4278     { 255, "Lennox International, Inc." },
4279     { 256, "RK-Tec Rauchklappen-Steuerungssysteme GmbH & Co. KG" },
4280     { 257, "Thermomax, Ltd." },
4281     { 258, "ELCON Electronic Control, Ltd." },
4282     { 259, "Larmia Control AB" },
4283     { 260, "BACnet Stack at SourceForge" },
4284     { 261, "G4S Security Services A/S" },
4285     { 262, "Exor International S.p.A." },
4286     { 263, "Cristal Controles" },
4287     { 264, "Regin AB" },
4288     { 265, "Dimension Software, Inc." },
4289     { 266, "SynapSense Corporation" },
4290     { 267, "Beijing Nantree Electronic Co., Ltd." },
4291     { 268, "Camus Hydronics Ltd." },
4292     { 269, "Kawasaki Heavy Industries, Ltd." },
4293     { 270, "Critical Environment Technologies" },
4294     { 271, "ILSHIN IBS Co., Ltd." },
4295     { 272, "ELESTA Energy Control AG" },
4296     { 273, "KROPMAN Installatietechniek" },
4297     { 274, "Baldor Electric Company" },
4298     { 275, "INGA mbH" },
4299     { 276, "GE Consumer & Industrial" },
4300     { 277, "Functional Devices, Inc." },
4301     { 278, "ESAC" },
4302     { 279, "M-System Co., Ltd." },
4303     { 280, "Yokota Co., Ltd." },
4304     { 281, "Hitranse Technology Co., LTD" },
4305     { 282, "Federspiel Controls" },
4306     { 283, "Kele, Inc." },
4307     { 284, "Opera Electronics, Inc." },
4308     { 285, "Gentec" },
4309     { 286, "Embedded Science Labs, LLC" },
4310     { 287, "Parker Hannifin Corporation" },
4311     { 288, "MaCaPS International Limited" },
4312     { 289, "Link4 Corporation" },
4313     { 290, "Romutec Steuer-u. Regelsysteme GmbH" },
4314     { 291, "Pribusin, Inc." },
4315     { 292, "Advantage Controls" },
4316     { 293, "Critical Room Control" },
4317     { 294, "LEGRAND" },
4318     { 295, "Tongdy Control Technology Co., Ltd." },
4319     { 296, "ISSARO Integrierte Systemtechnik" },
4320     { 297, "Pro-Dev Industries" },
4321     { 298, "DRI-STEEM" },
4322     { 299, "Creative Electronic GmbH" },
4323     { 300, "Swegon AB" },
4324     { 301, "Jan Brachacek" },
4325     { 302, "Hitachi Appliances, Inc." },
4326     { 303, "Real Time Automation, Inc." },
4327     { 304, "ITEC Hankyu-Hanshin Co." },
4328     { 305, "Cyrus E&M Engineering Co., Ltd." },
4329     { 306, "Badger Meter" },
4330     { 307, "Cirrascale Corporation" },
4331     { 308, "Elesta GmbH Building Automation" },
4332     { 309, "Securiton" },
4333     { 310, "OSlsoft, Inc." },
4334     { 311, "Hanazeder Electronic GmbH" },
4335     { 312, "Honeywell Security Deutschland, Novar GmbH" },
4336     { 313, "Siemens Energy & Automation, Inc." },
4337     { 314, "ETM Professional Control GmbH" },
4338     { 315, "Meitav-tec, Ltd." },
4339     { 316, "Janitza Electronics GmbH" },
4340     { 317, "MKS Nordhausen" },
4341     { 318, "De Gier Drive Systems B.V." },
4342     { 319, "Cypress Envirosystems" },
4343     { 320, "SMARTron s.r.o." },
4344     { 321, "Verari Systems, Inc." },
4345     { 322, "K-W Electronic Service, Inc." },
4346     { 323, "ALFA-SMART Energy Management" },
4347     { 324, "Telkonet, Inc." },
4348     { 325, "Securiton GmbH" },
4349     { 326, "Cemtrex, Inc." },
4350     { 327, "Performance Technologies, Inc." },
4351     { 328, "Xtralis (Aust) Pty Ltd" },
4352     { 329, "TROX GmbH" },
4353     { 330, "Beijing Hysine Technology Co., Ltd" },
4354     { 331, "RCK Controls, Inc." },
4355     { 332, "Distech Controls SAS" },
4356     { 333, "Novar/Honeywell" },
4357     { 334, "The S4 Group, Inc." },
4358     { 335, "Schneider Electric" },
4359     { 336, "LHA Systems" },
4360     { 337, "GHM engineering Group, Inc." },
4361     { 338, "Cllimalux S.A." },
4362     { 339, "VAISALA Oyj" },
4363     { 340, "COMPLEX (Beijing) Technology, Co., LTD." },
4364     { 341, "SCADAmetrics" },
4365     { 342, "POWERPEG NSI Limited" },
4366     { 343, "BACnet Interoperability Testing Services, Inc." },
4367     { 344, "Teco a.s." },
4368     { 345, "Plexus Technology, Inc." },
4369     { 346, "Energy Focus, Inc." },
4370     { 347, "Powersmiths International Corp." },
4371     { 348, "Nichibei Co., Ltd." },
4372     { 349, "HKC Technology Ltd." },
4373     { 350, "Ovation Networks, Inc." },
4374     { 351, "Setra Systems" },
4375     { 352, "AVG Automation" },
4376     { 353, "ZXC Ltd." },
4377     { 354, "Byte Sphere" },
4378     { 355, "Generiton Co., Ltd." },
4379     { 356, "Holter Regelarmaturen GmbH & Co. KG" },
4380     { 357, "Bedford Instruments, LLC" },
4381     { 358, "Standair Inc." },
4382     { 359, "WEG Automation - R&D" },
4383     { 360, "Prolon Control Systems ApS" },
4384     { 361, "Inneasoft" },
4385     { 362, "ConneXSoft GmbH" },
4386     { 363, "CEAG Notlichtsysteme GmbH" },
4387     { 364, "Distech Controls Inc." },
4388     { 365, "Industrial Technology Research Institute" },
4389     { 366, "ICONICS, Inc." },
4390     { 367, "IQ Controls s.c." },
4391     { 368, "OJ Electronics A/S" },
4392     { 369, "Rolbit Ltd." },
4393     { 370, "Synapsys Solutions Ltd." },
4394     { 371, "ACME Engineering Prod. Ltd." },
4395     { 372, "Zener Electric Pty, Ltd." },
4396     { 373, "Selectronix, Inc." },
4397     { 374, "Gorbet & Banerjee, LLC." },
4398     { 375, "IME" },
4399     { 376, "Stephen H. Dawson Computer Service" },
4400     { 377, "Accutrol, LLC" },
4401     { 378, "Schneider Elektronik GmbH" },
4402     { 379, "Alpha-Inno Tec GmbH" },
4403     { 380, "ADMMicro, Inc." },
4404     { 381, "Greystone Energy Systems, Inc." },
4405     { 382, "CAP Technologie" },
4406     { 383, "KeRo Systems" },
4407     { 384, "Domat Control System s.r.o." },
4408     { 385, "Efektronics Pty. Ltd." },
4409     { 386, "Hekatron Vertriebs GmbH" },
4410     { 387, "Securiton AG" },
4411     { 388, "Carlo Gavazzi Controls SpA" },
4412     { 389, "Chipkin Automation Systems" },
4413     { 390, "Savant Systems, LLC" },
4414     { 391, "Simmtronic Lighting Controls" },
4415     { 392, "Abelko Innovation AB" },
4416     { 393, "Seresco Technologies Inc." },
4417     { 394, "IT Watchdogs" },
4418     { 395, "Automation Assist Japan Corp." },
4419     { 396, "Thermokon Sensortechnik GmbH" },
4420     { 397, "EGauge Systems, LLC" },
4421     { 398, "Quantum Automation (ASIA) PTE, Ltd." },
4422     { 399, "Toshiba Lighting & Technology Corp." },
4423     { 400, "SPIN Engenharia de Automacao Ltda." },
4424     { 401, "Logistics Systems & Software Services India PVT. Ltd." },
4425     { 402, "Delta Controls Integration Products" },
4426     { 403, "Focus Media" },
4427     { 404, "LUMEnergi Inc." },
4428     { 405, "Kara Systems" },
4429     { 406, "RF Code, Inc." },
4430     { 407, "Fatek Automation Corp." },
4431     { 408, "JANDA Software Company, LLC" },
4432     { 409, "Open System Solutions Limited" },
4433     { 410, "Intelec Systems PTY Ltd." },
4434     { 411, "Ecolodgix, LLC" },
4435     { 412, "Douglas Lighting Controls" },
4436     { 413, "iSAtech GmbH" },
4437     { 414, "AREAL" },
4438     { 415, "Beckhoff Automation GmbH" },
4439     { 416, "IPAS GmbH" },
4440     { 417, "KE2 Therm Solutions" },
4441     { 418, "Base2Products" },
4442     { 419, "DTL Controls, LLC" },
4443     { 420, "INNCOM International, Inc." },
4444     { 421, "BTR Netcom GmbH" },
4445     { 422, "Greentrol Automation, Inc" },
4446     { 423, "BELIMO Automation AG" },
4447     { 424, "Samsung Heavy Industries Co, Ltd" },
4448     { 425, "Triacta Power Technologies, Inc." },
4449     { 426, "Globestar Systems" },
4450     { 427, "MLB Advanced Media, LP" },
4451     { 428, "SWG Stuckmann Wirtschaftliche Gebaeudesysteme GmbH" },
4452     { 429, "SensorSwitch" },
4453     { 430, "Multitek Power Limited" },
4454     { 431, "Aquametro AG" },
4455     { 432, "LG Electronics Inc." },
4456     { 433, "Electronic Theatre Controls, Inc." },
4457     { 434, "Mitsubishi Electric Corporation Nagoya Works" },
4458     { 435, "Delta Electronics, Inc." },
4459     { 436, "Elma Kurtalj, Ltd." },
4460     { 437, "ADT Fire and Security Sp. A.o.o." },
4461     { 438, "Nedap Security Management" },
4462     { 439, "ESC Automation Inc." },
4463     { 440, "DSP4YOU Ltd." },
4464     { 441, "GE Sensing and Inspection Technologies" },
4465     { 442, "Embedded Systems SIA" },
4466     { 443, "BEFEGA GmbH" },
4467     { 444, "Baseline Inc." },
4468     { 445, "M2M Systems Integrators" },
4469     { 446, "OEMCtrl" },
4470     { 447, "Clarkson Controls Limited" },
4471     { 448, "Rogerwell Control System Limited" },
4472     { 449, "SCL Elements" },
4473     { 450, "Hitachi Ltd." },
4474     { 451, "Newron System SA" },
4475     { 452, "BEVECO Gebouwautomatisering BV" },
4476     { 453, "Streamside Solutions" },
4477     { 454, "Yellowstone Soft" },
4478     { 455, "Oztech Intelligent Systems Pty Ltd." },
4479     { 456, "Novelan GmbH" },
4480     { 457, "Flexim Americas Corporation" },
4481     { 458, "ICP DAS Co., Ltd." },
4482     { 459, "CARMA Industries Inc." },
4483     { 460, "Log-One Ltd." },
4484     { 461, "TECO Electric & Machinery Co., Ltd." },
4485     { 462, "ConnectEx, Inc." },
4486     { 463, "Turbo DDC Suedwest" },
4487     { 464, "Quatrosense Environmental Ltd." },
4488     { 465, "Fifth Light Technology Ltd." },
4489     { 466, "Scientific Solutions, Ltd." },
4490     { 467, "Controller Area Network Solutions (M) Sdn Bhd" },
4491     { 468, "RESOL - Elektronische Regelungen GmbH" },
4492     { 469, "RPBUS LLC" },
4493     { 470, "BRS Sistemas Eletronicos" },
4494     { 471, "WindowMaster A/S" },
4495     { 472, "Sunlux Technologies Ltd." },
4496     { 473, "Measurlogic" },
4497     { 474, "Frimat GmbH" },
4498     { 475, "Spirax Sarco" },
4499     { 476, "Luxtron" },
4500     { 477, "Raypak Inc" },
4501     { 478, "Air Monitor Corporation" },
4502     { 479, "Regler Och Webbteknik Sverige (ROWS)" },
4503     { 480, "Intelligent Lighting Controls Inc." },
4504     { 481, "Sanyo Electric Industry Co., Ltd" },
4505     { 482, "E-Mon Energy Monitoring Products" },
4506     { 483, "Digital Control Systems" },
4507     { 484, "ATI Airtest Technologies, Inc." },
4508     { 485, "SCS SA" },
4509     { 486, "HMS Industrial Networks AB" },
4510     { 487, "Shenzhen Universal Intellisys Co Ltd" },
4511     { 488, "EK Intellisys Sdn Bhd" },
4512     { 489, "SysCom" },
4513     { 490, "Firecom, Inc." },
4514     { 491, "ESA Elektroschaltanlagen Grimma GmbH" },
4515     { 492, "Kumahira Co Ltd" },
4516     { 493, "Hotraco" },
4517     { 494, "SABO Elektronik GmbH" },
4518     { 495, "Equip'Trans" },
4519     { 496, "TCS Basys Controls" },
4520     { 497, "FlowCon International A/S" },
4521     { 498, "ThyssenKrupp Elevator Americas" },
4522     { 499, "Abatement Technologies" },
4523     { 500, "Continental Control Systems, LLC" },
4524     { 501, "WISAG Automatisierungstechnik GmbH & Co KG" },
4525     { 502, "EasyIO" },
4526     { 503, "EAP-Electric GmbH" },
4527     { 504, "Hardmeier" },
4528     { 505, "Mircom Group of Companies" },
4529     { 506, "Quest Controls" },
4530     { 507, "Mestek, Inc" },
4531     { 508, "Pulse Energy" },
4532     { 509, "Tachikawa Corporation" },
4533     { 510, "University of Nebraska-Lincoln" },
4534     { 511, "Redwood Systems" },
4535     { 512, "PASStec Industrie-Elektronik GmbH" },
4536     { 513, "NgEK, Inc." },
4537     { 514, "FAW Electronics Ltd" },
4538     { 515, "Jireh Energy Tech Co., Ltd." },
4539     { 516, "Enlighted Inc." },
4540     { 517, "El-Piast Sp. Z o.o" },
4541     { 518, "NetxAutomation Software GmbH" },
4542     { 519, "Invertek Drives" },
4543     { 520, "Deutschmann Automation GmbH & Co. KG" },
4544     { 521, "EMU Electronic AG" },
4545     { 522, "Phaedrus Limited" },
4546     { 523, "Sigmatek GmbH & Co KG" },
4547     { 524, "Marlin Controls" },
4548     { 525, "Circutor, SA" },
4549     { 526, "UTC Fire & Security" },
4550     { 527, "DENT Instruments, Inc." },
4551     { 528, "FHP Manufacturing Company - Bosch Group" },
4552     { 529, "GE Intelligent Platforms" },
4553     { 530, "Inner Range Pty Ltd" },
4554     { 531, "GLAS Energy Technology" },
4555     { 532, "MSR-Electronic-GmbH" },
4556     { 533, "Energy Control Systems, Inc." },
4557     { 534, "EMT Controls" },
4558     { 535, "Daintree Networks Inc." },
4559     { 536, "EURO ICC d.o.o" },
4560     { 537, "TE Connectivity Energy" },
4561     { 538, "GEZE GmbH" },
4562     { 539, "NEC Corporation" },
4563     { 540, "Ho Cheung International Company Limited" },
4564     { 541, "Sharp Manufacturing Systems Corporation" },
4565     { 542, "DOT CONTROLS a.s." },
4566     { 543, "BeaconMedaes" },
4567     { 544, "Midea Commercial Aircon" },
4568     { 545, "WattMaster Controls" },
4569     { 546, "Kamstrup A/S" },
4570     { 547, "CA Computer Automation GmbH" },
4571     { 548, "Laars Heating Systems Company" },
4572     { 549, "Hitachi Systems, Ltd." },
4573     { 550, "Fushan AKE Electronic Engineering Co., Ltd." },
4574     { 551, "Toshiba International Corporation" },
4575     { 552, "Starman Systems, LLC" },
4576     { 553, "Samsung Techwin Co., Ltd." },
4577     { 554, "ISAS-Integrated Switchgear and Systems P/L" },
4578     { 556, "Obvius" },
4579     { 557, "Marek Guzik" },
4580     { 558, "Vortek Instruments, LLC" },
4581     { 559, "Universal Lighting Technologies" },
4582     { 560, "Myers Power Products, Inc." },
4583     { 561, "Vector Controls GmbH" },
4584     { 562, "Crestron Electronics, Inc." },
4585     { 563, "A&E Controls Limited" },
4586     { 564, "Projektomontaza A.D." },
4587     { 565, "Freeaire Refrigeration" },
4588     { 566, "Aqua Cooler Pty Limited" },
4589     { 567, "Basic Controls" },
4590     { 568, "GE Measurement and Control Solutions Advanced Sensors" },
4591     { 569, "EQUAL Networks" },
4592     { 570, "Millennial Net" },
4593     { 571, "APLI Ltd" },
4594     { 572, "Electro Industries/GaugeTech" },
4595     { 573, "SangMyung University" },
4596     { 574, "Coppertree Analytics, Inc." },
4597     { 575, "CoreNetiX GmbH" },
4598     { 576, "Acutherm" },
4599     { 577, "Dr. Riedel Automatisierungstechnik GmbH" },
4600     { 578, "Shina System Co., Ltd" },
4601     { 579, "Iqapertus" },
4602     { 580, "PSE Technology" },
4603     { 581, "BA Systems" },
4604     { 582, "BTICINO" },
4605     { 583, "Monico, Inc." },
4606     { 584, "iCue" },
4607     { 585, "tekmar Control Systems Ltd." },
4608     { 586, "Control Technology Corporation" },
4609     { 587, "GFAE GmbH" },
4610     { 588, "BeKa Software GmbH" },
4611     { 589, "Isoil Industria SpA" },
4612     { 590, "Home Systems Consulting SpA" },
4613     { 591, "Socomec" },
4614     { 592, "Everex Communications, Inc." },
4615     { 593, "Ceiec Electric Technology" },
4616     { 594, "Atrila GmbH" },
4617     { 595, "WingTechs" },
4618     { 596, "Shenzhen Mek Intellisys Pte Ltd." },
4619     { 597, "Nestfield Co., Ltd." },
4620     { 598, "Swissphone Telecom AG" },
4621     { 599, "PNTECH JSC" },
4622     { 600, "Horner APG, LLC" },
4623     { 601, "PVI Industries, LLC" },
4624     { 602, "Ela-compil" },
4625     { 603, "Pegasus Automation International LLC" },
4626     { 604, "Wight Electronic Services Ltd." },
4627     { 605, "Marcom" },
4628     { 606, "Exhausto A/S" },
4629     { 607, "Dwyer Instruments, Inc." },
4630     { 608, "Link GmbH" },
4631     { 609, "Oppermann Regelgerate GmbH" },
4632     { 610, "NuAire, Inc." },
4633     { 611, "Nortec Humidity, Inc." },
4634     { 612, "Bigwood Systems, Inc." },
4635     { 613, "Enbala Power Networks" },
4636     { 614, "Inter Energy Co., Ltd." },
4637     { 615, "ETC" },
4638     { 616, "COMELEC S.A.R.L" },
4639     { 617, "Pythia Technologies" },
4640     { 618, "TrendPoint Systems, Inc." },
4641     { 619, "AWEX" },
4642     { 620, "Eurevia" },
4643     { 621, "Kongsberg E-lon AS" },
4644     { 622, "FlaktWoods" },
4645     { 623, "E + E Elektronik GES M.B.H." },
4646     { 624, "ARC Informatique" },
4647     { 625, "SKIDATA AG" },
4648     { 626, "WSW Solutions" },
4649     { 627, "Trefon Electronic GmbH" },
4650     { 628, "Dongseo System" },
4651     { 629, "Kanontec Intelligence Technology Co., Ltd." },
4652     { 630, "EVCO S.p.A." },
4653     { 631, "Accuenergy (CANADA) Inc." },
4654     { 632, "SoftDEL" },
4655     { 633, "Orion Energy Systems, Inc." },
4656     { 634, "Roboticsware" },
4657     { 635, "DOMIQ Sp. z o.o." },
4658     { 636, "Solidyne" },
4659     { 637, "Elecsys Corporation" },
4660     { 638, "Conditionaire International Pty. Limited" },
4661     { 639, "Quebec, Inc." },
4662     { 640, "Homerun Holdings" },
4663     { 641, "Murata Americas" },
4664     { 642, "Comptek" },
4665     { 643, "Westco Systems, Inc." },
4666     { 644, "Advancis Software & Services GmbH" },
4667     { 645, "Intergrid, LLC" },
4668     { 646, "Markerr Controls, Inc." },
4669     { 647, "Toshiba Elevator and Building Systems Corporation" },
4670     { 648, "Spectrum Controls, Inc." },
4671     { 649, "Mkservice" },
4672     { 650, "Fox Thermal Instruments" },
4673     { 651, "SyxthSense Ltd" },
4674     { 652, "DUHA System S R.O." },
4675     { 653, "NIBE" },
4676     { 654, "Melink Corporation" },
4677     { 655, "Fritz-Haber-Institut" },
4678     { 656, "MTU Onsite Energy GmbH, Gas Power Systems" },
4679     { 657, "Omega Engineering, Inc." },
4680     { 658, "Avelon" },
4681     { 659, "Ywire Technologies, Inc." },
4682     { 660, "M.R. Engineering Co., Ltd." },
4683     { 661, "Lochinvar, LLC" },
4684     { 662, "Sontay Limited" },
4685     { 663, "GRUPA Slawomir Chelminski" },
4686     { 664, "Arch Meter Corporation" },
4687     { 665, "Senva, Inc." },
4688     { 667, "FM-Tec" },
4689     { 668, "Systems Specialists, Inc." },
4690     { 669, "SenseAir" },
4691     { 670, "AB IndustrieTechnik Srl" },
4692     { 671, "Cortland Research, LLC" },
4693     { 672, "MediaView" },
4694     { 673, "VDA Elettronica" },
4695     { 674, "CSS, Inc." },
4696     { 675, "Tek-Air Systems, Inc." },
4697     { 676, "ICDT" },
4698     { 677, "The Armstrong Monitoring Corporation" },
4699     { 678, "DIXELL S.r.l" },
4700     { 679, "Lead System, Inc." },
4701     { 680, "ISM EuroCenter S.A." },
4702     { 681, "TDIS" },
4703     { 682, "Trade FIDES" },
4704     { 683, "Knuerr GmbH (Emerson Network Power)" },
4705     { 684, "Resource Data Management" },
4706     { 685, "Abies Technology, Inc." },
4707     { 686, "Amalva" },
4708     { 687, "MIRAE Electrical Mfg. Co., Ltd." },
4709     { 688, "HunterDouglas Architectural Projects Scandinavia ApS" },
4710     { 689, "RUNPAQ Group Co., Ltd" },
4711     { 690, "Unicard SA" },
4712     { 691, "IE Technologies" },
4713     { 692, "Ruskin Manufacturing" },
4714     { 693, "Calon Associates Limited" },
4715     { 694, "Contec Co., Ltd." },
4716     { 695, "iT GmbH" },
4717     { 696, "Autani Corporation" },
4718     { 697, "Christian Fortin" },
4719     { 698, "HDL" },
4720     { 699, "IPID Sp. Z.O.O Limited" },
4721     { 700, "Fuji Electric Co., Ltd" },
4722     { 701, "View, Inc." },
4723     { 702, "Samsung S1 Corporation" },
4724     { 703, "New Lift" },
4725     { 704, "VRT Systems" },
4726     { 705, "Motion Control Engineering, Inc." },
4727     { 706, "Weiss Klimatechnik GmbH" },
4728     { 707, "Elkon" },
4729     { 708, "Eliwell Controls S.r.l." },
4730     { 709, "Japan Computer Technos Corp" },
4731     { 710, "Rational Network ehf" },
4732     { 711, "Magnum Energy Solutions, LLC" },
4733     { 712, "MelRok" },
4734     { 713, "VAE Group" },
4735     { 714, "LGCNS" },
4736     { 715, "Berghof Automationstechnik GmbH" },
4737     { 716, "Quark Communications, Inc." },
4738     { 717, "Sontex" },
4739     { 718, "mivune AG" },
4740     { 719, "Panduit" },
4741     { 720, "Smart Controls, LLC" },
4742     { 721, "Compu-Aire, Inc." },
4743     { 722, "Sierra" },
4744     { 723, "ProtoSense Technologies" },
4745     { 724, "Eltrac Technologies Pvt Ltd" },
4746     { 725, "Bektas Invisible Controls GmbH" },
4747     { 726, "Entelec" },
4748     { 727, "Innexiv" },
4749     { 728, "Covenant" },
4750     { 729, "Davitor AB" },
4751     { 730, "TongFang Technovator" },
4752     { 731, "Building Robotics, Inc." },
4753     { 732, "HSS-MSR UG" },
4754     { 733, "FramTack LLC" },
4755     { 734, "B. L. Acoustics, Ltd." },
4756     { 735, "Traxxon Rock Drills, Ltd" },
4757     { 736, "Franke" },
4758     { 737, "Wurm GmbH & Co" },
4759     { 738, "AddENERGIE" },
4760     { 739, "Mirle Automation Corporation" },
4761     { 740, "Ibis Networks" },
4762     { 741, "ID-KARTA s.r.o." },
4763     { 742, "Anaren, Inc." },
4764     { 743, "Span, Incorporated" },
4765     { 744, "Bosch Thermotechnology Corp" },
4766     { 745, "DRC Technology S.A." },
4767     { 746, "Shanghai Energy Building Technology Co, Ltd" },
4768     { 747, "Fraport AG" },
4769     { 748, "Flowgroup" },
4770     { 749, "Skytron Energy, GmbH" },
4771     { 750, "ALTEL Wicha, Golda Sp. J." },
4772     { 751, "Drupal" },
4773     { 752, "Axiomatic Technology, Ltd" },
4774     { 753, "Bohnke + Partner" },
4775     { 754, "Function 1" },
4776     { 755, "Optergy Pty, Ltd" },
4777     { 756, "LSI Virticus" },
4778     { 757, "Konzeptpark GmbH" },
4779     { 758, "Hubbell Building Automation, Inc." },
4780     { 759, "eCurv, Inc." },
4781     { 760, "Agnosys GmbH" },
4782     { 761, "Shanghai Sunfull Automation Co., LTD" },
4783     { 762, "Kurz Instruments, Inc." },
4784     { 763, "Cias Elettronica S.r.l." },
4785     { 764, "Multiaqua, Inc." },
4786     { 765, "BlueBox" },
4787     { 766, "Sensidyne" },
4788     { 767, "Viessmann Elektronik GmbH" },
4789     { 768, "ADFweb.com srl" },
4790     { 769, "Gaylord Industries" },
4791     { 770, "Majur Ltd." },
4792     { 771, "Shanghai Huilin Technology Co., Ltd." },
4793     { 772, "Exotronic" },
4794     { 773, "Safecontrol spol s.r.o." },
4795     { 774, "Amatis" },
4796     { 775, "Universal Electric Corporation" },
4797     { 776, "iBACnet" },
4798     { 778, "Smartrise Engineering, Inc." },
4799     { 779, "Miratron, Inc." },
4800     { 780, "SmartEdge" },
4801     { 781, "Mitsubishi Electric Australia Pty Ltd" },
4802     { 782, "Triangle Research International Ptd Ltd" },
4803     { 783, "Produal Oy" },
4804     { 784, "Milestone Systems A/S" },
4805     { 785, "Trustbridge" },
4806     { 0, NULL }
4807 };
4808 static value_string_ext BACnetVendorIdentifiers_ext = VALUE_STRING_EXT_INIT(BACnetVendorIdentifiers);
4809
4810 static int proto_bacapp = -1;
4811 static int hf_bacapp_type = -1;
4812 static int hf_bacapp_pduflags = -1;
4813 static int hf_bacapp_SEG = -1;
4814 static int hf_bacapp_MOR = -1;
4815 static int hf_bacapp_SA = -1;
4816 static int hf_bacapp_response_segments = -1;
4817 static int hf_bacapp_max_adpu_size = -1;
4818 static int hf_bacapp_invoke_id = -1;
4819 static int hf_bacapp_objectType = -1;
4820 static int hf_bacapp_instanceNumber = -1;
4821 static int hf_bacapp_sequence_number = -1;
4822 static int hf_bacapp_window_size = -1;
4823 static int hf_bacapp_service = -1;
4824 static int hf_bacapp_NAK = -1;
4825 static int hf_bacapp_SRV = -1;
4826 static int hf_Device_Instance_Range_Low_Limit = -1;
4827 static int hf_Device_Instance_Range_High_Limit = -1;
4828 static int hf_BACnetRejectReason = -1;
4829 static int hf_BACnetAbortReason = -1;
4830 static int hf_BACnetApplicationTagNumber = -1;
4831 static int hf_BACnetContextTagNumber = -1;
4832 static int hf_BACnetExtendedTagNumber = -1;
4833 static int hf_BACnetNamedTag = -1;
4834 static int hf_BACnetTagClass = -1;
4835 static int hf_BACnetCharacterSet = -1;
4836 static int hf_BACnetCodePage = -1;
4837 static int hf_bacapp_tag_lvt = -1;
4838 static int hf_bacapp_tag_ProcessId = -1;
4839 static int hf_bacapp_uservice = -1;
4840 static int hf_BACnetPropertyIdentifier = -1;
4841 static int hf_BACnetVendorIdentifier = -1;
4842 static int hf_BACnetRestartReason = -1;
4843 static int hf_bacapp_tag_IPV4 = -1;
4844 static int hf_bacapp_tag_IPV6 = -1;
4845 static int hf_bacapp_tag_PORT = -1;
4846 /* some more variables for segmented messages */
4847 static int hf_msg_fragments = -1;
4848 static int hf_msg_fragment = -1;
4849 static int hf_msg_fragment_overlap = -1;
4850 static int hf_msg_fragment_overlap_conflicts = -1;
4851 static int hf_msg_fragment_multiple_tails = -1;
4852 static int hf_msg_fragment_too_long_fragment = -1;
4853 static int hf_msg_fragment_error = -1;
4854 static int hf_msg_fragment_count = -1;
4855 static int hf_msg_reassembled_in = -1;
4856 static int hf_msg_reassembled_length = -1;
4857
4858 static gint ett_msg_fragment = -1;
4859 static gint ett_msg_fragments = -1;
4860
4861 static gint ett_bacapp = -1;
4862 static gint ett_bacapp_control = -1;
4863 static gint ett_bacapp_tag = -1;
4864 static gint ett_bacapp_list = -1;
4865 static gint ett_bacapp_value = -1;
4866
4867 static expert_field ei_bacapp_bad_length = EI_INIT;
4868 static expert_field ei_bacapp_bad_tag = EI_INIT;
4869
4870 static gint32 propertyIdentifier = -1;
4871 static gint32 propertyArrayIndex = -1;
4872 static guint32 object_type = 4096;
4873
4874 static guint8 bacapp_flags = 0;
4875 static guint8 bacapp_seq = 0;
4876
4877 /* Defined to allow vendor identifier registration of private transfer dissectors */
4878 static dissector_table_t bacapp_dissector_table;
4879
4880
4881 /* Stat: BACnet Packets sorted by IP */
4882 bacapp_info_value_t bacinfo;
4883
4884 static const gchar* st_str_packets_by_ip = "BACnet Packets by IP";
4885 static const gchar* st_str_packets_by_ip_dst = "By Destination";
4886 static const gchar* st_str_packets_by_ip_src = "By Source";
4887 static int st_node_packets_by_ip = -1;
4888 static int st_node_packets_by_ip_dst = -1;
4889 static int st_node_packets_by_ip_src = -1;
4890
4891 static void
4892 bacapp_packet_stats_tree_init(stats_tree* st)
4893 {
4894     st_node_packets_by_ip = stats_tree_create_pivot(st, st_str_packets_by_ip, 0);
4895     st_node_packets_by_ip_src = stats_tree_create_node(st, st_str_packets_by_ip_src, st_node_packets_by_ip, TRUE);
4896     st_node_packets_by_ip_dst = stats_tree_create_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, TRUE);
4897 }
4898
4899 static gchar *
4900 bacapp_get_address_label(const char *tag, address *addr)
4901 {
4902     gchar *addr_str, *label_str;
4903
4904     addr_str = address_to_str(NULL, addr);
4905     label_str = wmem_strconcat(NULL, tag, addr_str, NULL);
4906     wmem_free(NULL, addr_str);
4907     return label_str;
4908 }
4909
4910 static int
4911 bacapp_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4912 {
4913     int    packets_for_this_dst;
4914     int    packets_for_this_src;
4915     int    service_for_this_dst;
4916     int    service_for_this_src;
4917     int    src_for_this_dst;
4918     int    dst_for_this_src;
4919     int    objectid_for_this_dst;
4920     int    objectid_for_this_src;
4921     int    instanceid_for_this_dst;
4922     int    instanceid_for_this_src;
4923     gchar *dststr;
4924     gchar *srcstr;
4925     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4926
4927     srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
4928     dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
4929
4930     tick_stat_node(st, st_str_packets_by_ip, 0, TRUE);
4931     packets_for_this_dst = tick_stat_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, TRUE);
4932     packets_for_this_src = tick_stat_node(st, st_str_packets_by_ip_src, st_node_packets_by_ip, TRUE);
4933     src_for_this_dst     = tick_stat_node(st, dststr, packets_for_this_dst, TRUE);
4934     dst_for_this_src     = tick_stat_node(st, srcstr, packets_for_this_src, TRUE);
4935     service_for_this_src = tick_stat_node(st, dststr, dst_for_this_src, TRUE);
4936     service_for_this_dst = tick_stat_node(st, srcstr, src_for_this_dst, TRUE);
4937     if (binfo->service_type) {
4938         objectid_for_this_dst = tick_stat_node(st, binfo->service_type, service_for_this_dst, TRUE);
4939         objectid_for_this_src = tick_stat_node(st, binfo->service_type, service_for_this_src, TRUE);
4940         if (binfo->object_ident) {
4941             instanceid_for_this_dst = tick_stat_node(st, binfo->object_ident, objectid_for_this_dst, TRUE);
4942             tick_stat_node(st, binfo->instance_ident, instanceid_for_this_dst, FALSE);
4943             instanceid_for_this_src = tick_stat_node(st, binfo->object_ident, objectid_for_this_src, TRUE);
4944             tick_stat_node(st, binfo->instance_ident, instanceid_for_this_src, FALSE);
4945         }
4946     }
4947
4948     wmem_free(NULL, srcstr);
4949     wmem_free(NULL, dststr);
4950
4951     return 1;
4952 }
4953
4954 /* Stat: BACnet Packets sorted by Service */
4955 static const gchar* st_str_packets_by_service = "BACnet Packets by Service";
4956 static int st_node_packets_by_service = -1;
4957
4958 static void
4959 bacapp_service_stats_tree_init(stats_tree* st)
4960 {
4961     st_node_packets_by_service = stats_tree_create_pivot(st, st_str_packets_by_service, 0);
4962 }
4963
4964 static int
4965 bacapp_stats_tree_service(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4966 {
4967     int    servicetype;
4968     int    src, dst;
4969     int    objectid;
4970
4971     gchar *dststr;
4972     gchar *srcstr;
4973
4974     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4975
4976     srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
4977     dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
4978
4979     tick_stat_node(st, st_str_packets_by_service, 0, TRUE);
4980     if (binfo->service_type) {
4981         servicetype = tick_stat_node(st, binfo->service_type, st_node_packets_by_service, TRUE);
4982         src         = tick_stat_node(st, srcstr, servicetype, TRUE);
4983         dst         = tick_stat_node(st, dststr, src, TRUE);
4984         if (binfo->object_ident) {
4985             objectid = tick_stat_node(st, binfo->object_ident, dst, TRUE);
4986             tick_stat_node(st, binfo->instance_ident, objectid, FALSE);
4987         }
4988     }
4989
4990     wmem_free(NULL, srcstr);
4991     wmem_free(NULL, dststr);
4992
4993     return 1;
4994 }
4995
4996 /* Stat: BACnet Packets sorted by Object Type */
4997 static const gchar* st_str_packets_by_objectid = "BACnet Packets by Object Type";
4998 static int st_node_packets_by_objectid = -1;
4999
5000 static void
5001 bacapp_objectid_stats_tree_init(stats_tree* st)
5002 {
5003     st_node_packets_by_objectid = stats_tree_create_pivot(st, st_str_packets_by_objectid, 0);
5004 }
5005
5006 static int
5007 bacapp_stats_tree_objectid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
5008 {
5009     int    servicetype;
5010     int    src, dst;
5011     int    objectid;
5012
5013     gchar *dststr;
5014     gchar *srcstr;
5015     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
5016
5017     srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
5018     dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
5019
5020     tick_stat_node(st, st_str_packets_by_objectid, 0, TRUE);
5021     if (binfo->object_ident) {
5022         objectid = tick_stat_node(st, binfo->object_ident, st_node_packets_by_objectid, TRUE);
5023         src = tick_stat_node(st, srcstr, objectid, TRUE);
5024         dst = tick_stat_node(st, dststr, src, TRUE);
5025         if (binfo->service_type) {
5026             servicetype = tick_stat_node(st, binfo->service_type, dst, TRUE);
5027             tick_stat_node(st, binfo->instance_ident, servicetype, FALSE);
5028         }
5029     }
5030
5031     wmem_free(NULL, srcstr);
5032     wmem_free(NULL, dststr);
5033
5034     return 1;
5035 }
5036
5037 /* Stat: BACnet Packets sorted by Instance No */
5038 static const gchar* st_str_packets_by_instanceid  = "BACnet Packets by Instance ID";
5039 static int          st_node_packets_by_instanceid = -1;
5040
5041 static void
5042 bacapp_instanceid_stats_tree_init(stats_tree* st)
5043 {
5044     st_node_packets_by_instanceid = stats_tree_create_pivot(st, st_str_packets_by_instanceid, 0);
5045 }
5046
5047 static int
5048 bacapp_stats_tree_instanceid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
5049 {
5050     int    servicetype;
5051     int    src, dst;
5052     int    instanceid;
5053
5054     gchar *dststr;
5055     gchar *srcstr;
5056     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
5057
5058     srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
5059     dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
5060
5061     tick_stat_node(st, st_str_packets_by_instanceid, 0, TRUE);
5062     if (binfo->object_ident) {
5063         instanceid = tick_stat_node(st, binfo->instance_ident, st_node_packets_by_instanceid, TRUE);
5064         src = tick_stat_node(st, srcstr, instanceid, TRUE);
5065         dst = tick_stat_node(st, dststr, src, TRUE);
5066         if (binfo->service_type) {
5067             servicetype = tick_stat_node(st, binfo->service_type, dst, TRUE);
5068             tick_stat_node(st, binfo->object_ident, servicetype, FALSE);
5069         }
5070     }
5071
5072     wmem_free(NULL, srcstr);
5073     wmem_free(NULL, dststr);
5074
5075     return 1;
5076 }
5077
5078
5079 /* register all BACnet Ststistic trees */
5080 static void
5081 register_bacapp_stat_trees(void)
5082 {
5083     stats_tree_register("bacapp", "bacapp_ip", "BACnet/Packets sorted by IP", 0,
5084         bacapp_stats_tree_packet, bacapp_packet_stats_tree_init, NULL);
5085     stats_tree_register("bacapp", "bacapp_service", "BACnet/Packets sorted by Service", 0,
5086         bacapp_stats_tree_service, bacapp_service_stats_tree_init, NULL);
5087     stats_tree_register("bacapp", "bacapp_objectid", "BACnet/Packets sorted by Object Type", 0,
5088         bacapp_stats_tree_objectid, bacapp_objectid_stats_tree_init, NULL);
5089     stats_tree_register("bacapp", "bacapp_instanceid", "BACnet/Packets sorted by Instance ID", 0,
5090         bacapp_stats_tree_instanceid, bacapp_instanceid_stats_tree_init, NULL);
5091 }
5092
5093 /* 'data' must be allocated with wmem packet scope */
5094 static gint
5095 updateBacnetInfoValue(gint whichval, const gchar *data)
5096 {
5097     if (whichval == BACINFO_SERVICE) {
5098         bacinfo.service_type = data;
5099         return 0;
5100     }
5101     if (whichval == BACINFO_INVOKEID) {
5102         bacinfo.invoke_id = data;
5103         return 0;
5104     }
5105     if (whichval == BACINFO_OBJECTID) {
5106         bacinfo.object_ident = data;
5107         return 0;
5108     }
5109     if (whichval == BACINFO_INSTANCEID) {
5110         bacinfo.instance_ident = data;
5111         return 0;
5112     }
5113     return -1;
5114 }
5115
5116 static const fragment_items msg_frag_items = {
5117     /* Fragment subtrees */
5118     &ett_msg_fragment,
5119     &ett_msg_fragments,
5120     /* Fragment fields */
5121     &hf_msg_fragments,
5122     &hf_msg_fragment,
5123     &hf_msg_fragment_overlap,
5124     &hf_msg_fragment_overlap_conflicts,
5125     &hf_msg_fragment_multiple_tails,
5126     &hf_msg_fragment_too_long_fragment,
5127     &hf_msg_fragment_error,
5128     &hf_msg_fragment_count,
5129     /* Reassembled in field */
5130     &hf_msg_reassembled_in,
5131     /* Reassembled length field */
5132     &hf_msg_reassembled_length,
5133     /* Reassembled data field */
5134     NULL,
5135     /* Tag */
5136     "Message fragments"
5137 };
5138
5139 #if 0
5140 /* if BACnet uses the reserved values, then patch the corresponding values here, maximum 16 values are defined */
5141 /* FIXME: fGetMaxAPDUSize is commented out, as it is not used. It was used to set variables which were not later used. */
5142 static const guint MaxAPDUSize [] = { 50, 128, 206, 480, 1024, 1476 };
5143
5144 static guint
5145 fGetMaxAPDUSize(guint8 idx)
5146 {
5147     /* only 16 values are defined, so use & 0x0f */
5148     /* check the size of the Array, deliver either the entry
5149        or the first entry if idx is outside of the array (bug 3736 comment#7) */
5150
5151     if ((idx & 0x0f) >= (gint)(sizeof(MaxAPDUSize)/sizeof(guint)))
5152         return MaxAPDUSize[0];
5153     else
5154         return MaxAPDUSize[idx & 0x0f];
5155 }
5156 #endif
5157
5158 static const char*
5159 val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
5160     const char *fmt, const char *split_fmt)
5161     G_GNUC_PRINTF(4, 0)
5162     G_GNUC_PRINTF(5, 0);
5163
5164 /* Used when there are ranges of reserved and proprietary enumerations */
5165 static const char*
5166 val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
5167     const char *fmt, const char *split_fmt)
5168 {
5169     if (val < split_val)
5170         return val_to_str(val, vs, fmt);
5171     else
5172         return val_to_str(val, vs, split_fmt);
5173 }
5174
5175 /* from clause 20.2.1.3.2 Constructed Data */
5176 /* returns true if the extended value is used */
5177 static gboolean
5178 tag_is_extended_value(guint8 tag)
5179 {
5180     return (tag & 0x07) == 5;
5181 }
5182
5183 static gboolean
5184 tag_is_opening(guint8 tag)
5185 {
5186     return (tag & 0x07) == 6;
5187 }
5188
5189 static gboolean
5190 tag_is_closing(guint8 tag)
5191 {
5192     return (tag & 0x07) == 7;
5193 }
5194
5195 /* from clause 20.2.1.1 Class
5196    class bit shall be one for context specific tags */
5197 /* returns true if the tag is context specific */
5198 static gboolean
5199 tag_is_context_specific(guint8 tag)
5200 {
5201     return (tag & 0x08) != 0;
5202 }
5203
5204 static gboolean
5205 tag_is_extended_tag_number(guint8 tag)
5206 {
5207     return ((tag & 0xF0) == 0xF0);
5208 }
5209
5210 static guint32
5211 object_id_type(guint32 object_identifier)
5212 {
5213     return ((object_identifier >> 22) & 0x3FF);
5214 }
5215
5216 static guint32
5217 object_id_instance(guint32 object_identifier)
5218 {
5219     return (object_identifier & 0x3FFFFF);
5220 }
5221
5222 static guint
5223 fTagNo(tvbuff_t *tvb, guint offset)
5224 {
5225     return (guint)(tvb_get_guint8(tvb, offset) >> 4);
5226 }
5227
5228 static gboolean
5229 fUnsigned32(tvbuff_t *tvb, guint offset, guint32 lvt, guint32 *val)
5230 {
5231     gboolean valid = TRUE;
5232
5233     switch (lvt) {
5234     case 1:
5235         *val = tvb_get_guint8(tvb, offset);
5236         break;
5237     case 2:
5238         *val = tvb_get_ntohs(tvb, offset);
5239         break;
5240     case 3:
5241         *val = tvb_get_ntoh24(tvb, offset);
5242         break;
5243     case 4:
5244         *val = tvb_get_ntohl(tvb, offset);
5245         break;
5246     default:
5247         valid = FALSE;
5248         break;
5249     }
5250
5251     return valid;
5252 }
5253
5254 static gboolean
5255 fUnsigned64(tvbuff_t *tvb, guint offset, guint32 lvt, guint64 *val)
5256 {
5257     gboolean valid = FALSE;
5258     gint64   value = 0;
5259     guint8   data, i;
5260
5261     if (lvt && (lvt <= 8)) {
5262         valid = TRUE;
5263         for (i = 0; i < lvt; i++) {
5264             data = tvb_get_guint8(tvb, offset+i);
5265             value = (value << 8) + data;
5266         }
5267         *val = value;
5268     }
5269
5270     return valid;
5271 }
5272
5273 /* BACnet Signed Value uses 2's complement notation, but with a twist:
5274    All signed integers shall be encoded in the smallest number of octets
5275    possible.  That is, the first octet of any multi-octet encoded value
5276    shall not be X'00' if the most significant bit (bit 7) of the second
5277    octet is 0, and the first octet shall not be X'FF' if the most
5278    significant bit of the second octet is 1. ASHRAE-135-2004-20.2.5 */
5279 static gboolean
5280 fSigned64(tvbuff_t *tvb, guint offset, guint32 lvt, gint64 *val)
5281 {
5282     gboolean valid = FALSE;
5283     gint64   value = 0;
5284     guint8   data;
5285     guint32  i;
5286
5287     /* we can only handle 7 bytes for a 64-bit value due to signed-ness */
5288     if (lvt && (lvt <= 7)) {
5289         valid = TRUE;
5290         data = tvb_get_guint8(tvb, offset);
5291         if ((data & 0x80) != 0)
5292             value = (-1 << 8) | data;
5293         else
5294             value = data;
5295         for (i = 1; i < lvt; i++) {
5296             data = tvb_get_guint8(tvb, offset+i);
5297             value = (value << 8) + data;
5298         }
5299         *val = value;
5300     }
5301
5302     return valid;
5303 }
5304
5305 static guint
5306 fTagHeaderTree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5307     guint offset, guint8 *tag_no, guint8* tag_info, guint32 *lvt)
5308 {
5309     proto_item *ti = NULL;
5310     guint8      tag;
5311     guint8      value;
5312     guint       tag_len = 1;
5313     guint       lvt_len = 1;    /* used for tree display of lvt */
5314     guint       lvt_offset;     /* used for tree display of lvt */
5315
5316     lvt_offset = offset;
5317     tag        = tvb_get_guint8(tvb, offset);
5318     *tag_info  = 0;
5319     *lvt       = tag & 0x07;
5320
5321     /* To solve the problem of lvt values of 6/7 being indeterminate - it */
5322     /* can mean open/close tag or length of 6/7 after the length is */
5323     /* computed below - store whole tag info, not just context bit. */
5324     if (tag_is_context_specific(tag)) *tag_info = tag & 0x0F;
5325     *tag_no = tag >> 4;
5326     if (tag_is_extended_tag_number(tag)) {
5327         *tag_no = tvb_get_guint8(tvb, offset + tag_len++);
5328     }
5329     if (tag_is_extended_value(tag)) {       /* length is more than 4 Bytes */
5330         lvt_offset += tag_len;
5331         value = tvb_get_guint8(tvb, lvt_offset);
5332         tag_len++;
5333         if (value == 254) { /* length is encoded with 16 Bits */
5334             *lvt = tvb_get_ntohs(tvb, lvt_offset+1);
5335             tag_len += 2;
5336             lvt_len += 2;
5337         } else if (value == 255) { /* length is encoded with 32 Bits */
5338             *lvt = tvb_get_ntohl(tvb, lvt_offset+1);
5339             tag_len += 4;
5340             lvt_len += 4;
5341         } else
5342             *lvt = value;
5343     }
5344
5345     if (tree) {
5346         proto_tree *subtree;
5347         if (tag_is_opening(tag)) {
5348             subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
5349                     ett_bacapp_tag, &ti, "{[%u]", *tag_no );
5350         } else if (tag_is_closing(tag)) {
5351             subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
5352                     ett_bacapp_tag, &ti, "}[%u]", *tag_no );
5353         } else if (tag_is_context_specific(tag)) {
5354             subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
5355                     ett_bacapp_tag, &ti,
5356                     "Context Tag: %u, Length/Value/Type: %u", *tag_no, *lvt);
5357         } else {
5358             subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
5359                     ett_bacapp_tag, &ti,
5360                     "Application Tag: %s, Length/Value/Type: %u",
5361                     val_to_str(*tag_no, BACnetApplicationTagNumber,
5362                         ASHRAE_Reserved_Fmt),
5363                     *lvt);
5364         }
5365
5366         /* details if needed */
5367         proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, ENC_BIG_ENDIAN);
5368         if (tag_is_extended_tag_number(tag)) {
5369             proto_tree_add_uint_format(subtree,
5370                                        hf_BACnetContextTagNumber,
5371                                        tvb, offset, 1, tag,
5372                                        "Extended Tag Number");
5373             proto_tree_add_item(subtree,
5374                                 hf_BACnetExtendedTagNumber,
5375                                 tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5376         } else {
5377             if (tag_is_context_specific(tag))
5378                 proto_tree_add_item(subtree,
5379                                     hf_BACnetContextTagNumber,
5380                                     tvb, offset, 1, ENC_BIG_ENDIAN);
5381             else
5382                 proto_tree_add_item(subtree,
5383                                     hf_BACnetApplicationTagNumber,
5384                                     tvb, offset, 1, ENC_BIG_ENDIAN);
5385         }
5386         if (tag_is_closing(tag) || tag_is_opening(tag))
5387             proto_tree_add_item(subtree,
5388                                 hf_BACnetNamedTag,
5389                                 tvb, offset, 1, ENC_BIG_ENDIAN);
5390         else if (tag_is_extended_value(tag)) {
5391             proto_tree_add_item(subtree,
5392                                 hf_BACnetNamedTag,
5393                                 tvb, offset, 1, ENC_BIG_ENDIAN);
5394             proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
5395                                 tvb, lvt_offset, lvt_len, *lvt);
5396         } else
5397             proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
5398                                 tvb, lvt_offset, lvt_len, *lvt);
5399     } /* if (tree) */
5400
5401     if (*lvt > tvb_reported_length(tvb)) {
5402         expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
5403                                "LVT length too long: %d > %d", *lvt,
5404                                tvb_reported_length(tvb));
5405         *lvt = 1;
5406     }
5407
5408     return tag_len;
5409 }
5410
5411 static guint
5412 fTagHeader(tvbuff_t *tvb, packet_info *pinfo, guint offset, guint8 *tag_no, guint8* tag_info,
5413     guint32 *lvt)
5414 {
5415     return fTagHeaderTree(tvb, pinfo, NULL, offset, tag_no, tag_info, lvt);
5416 }
5417
5418 static guint
5419 fNullTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5420 {
5421     guint8      tag_no, tag_info;
5422     guint32     lvt;
5423     proto_tree *subtree;
5424
5425     subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "%sNULL", label);
5426     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5427
5428     return offset + 1;
5429 }
5430
5431 static guint
5432 fBooleanTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5433 {
5434     guint8      tag_no, tag_info;
5435     guint32     lvt      = 0;
5436     proto_tree *subtree;
5437     guint       bool_len = 1;
5438
5439     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5440     if (tag_info && lvt == 1) {
5441         lvt = tvb_get_guint8(tvb, offset+1);
5442         ++bool_len;
5443     }
5444
5445     subtree = proto_tree_add_subtree_format(tree, tvb, offset, bool_len,
5446                              ett_bacapp_tag, NULL, "%s%s", label, lvt == 0 ? "FALSE" : "TRUE");
5447     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5448
5449     return offset + bool_len;
5450 }
5451
5452 static guint
5453 fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5454 {
5455     guint64     val = 0;
5456     guint8      tag_no, tag_info;
5457     guint32     lvt;
5458     guint       tag_len;
5459     proto_tree *subtree;
5460
5461     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5462     /* only support up to an 8 byte (64-bit) integer */
5463     if (fUnsigned64(tvb, offset + tag_len, lvt, &val))
5464         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5465             ett_bacapp_tag, NULL, "%s(Unsigned) %" G_GINT64_MODIFIER "u", label, val);
5466     else
5467         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5468             ett_bacapp_tag, NULL, "%s - %u octets (Unsigned)", label, lvt);
5469     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5470
5471     return offset+tag_len+lvt;
5472 }
5473
5474 static guint
5475 fDevice_Instance(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, int hf)
5476 {
5477     guint8      tag_no, tag_info;
5478     guint32     lvt, safe_lvt;
5479     guint       tag_len;
5480     proto_item *ti;
5481     proto_tree *subtree;
5482
5483     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5484
5485     if (lvt > 4)
5486         safe_lvt = 4;
5487     else
5488         safe_lvt = lvt;
5489
5490     ti = proto_tree_add_item(tree, hf, tvb, offset+tag_len, safe_lvt, ENC_BIG_ENDIAN);
5491
5492     if (lvt != safe_lvt)
5493         expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
5494                 "This field claims to be an impossible %u bytes, while the max is %u", lvt, safe_lvt);
5495
5496     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5497     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5498
5499     return offset+tag_len+lvt;
5500 }
5501
5502 /* set split_val to zero when not needed */
5503 static guint
5504 fEnumeratedTagSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5505     guint offset, const gchar *label, const value_string *vs, guint32 split_val)
5506 {
5507     guint32     val = 0;
5508     guint8      tag_no, tag_info;
5509     guint32     lvt;
5510     guint       tag_len;
5511     proto_tree *subtree;
5512
5513     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5514     /* only support up to a 4 byte (32-bit) enumeration */
5515     if (fUnsigned32(tvb, offset+tag_len, lvt, &val)) {
5516         if (vs)
5517             subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5518                 ett_bacapp_tag, NULL, "%s %s", label, val_to_split_str(val, split_val, vs,
5519                 ASHRAE_Reserved_Fmt, Vendor_Proprietary_Fmt));
5520         else
5521             subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5522                 ett_bacapp_tag, NULL, "%s %u", label, val);
5523     } else {
5524         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5525             ett_bacapp_tag, NULL, "%s - %u octets (enumeration)", label, lvt);
5526     }
5527
5528     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5529
5530     return offset+tag_len+lvt;
5531 }
5532
5533 static guint
5534 fEnumeratedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5535         guint offset, const gchar *label, const value_string *vs)
5536 {
5537     return fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, vs, 0);
5538 }
5539
5540 static guint
5541 fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5542 {
5543     gint64      val = 0;
5544     guint8      tag_no, tag_info;
5545     guint32     lvt;
5546     guint       tag_len;
5547     proto_tree *subtree;
5548
5549     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5550     if (fSigned64(tvb, offset + tag_len, lvt, &val))
5551         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5552             ett_bacapp_tag, NULL, "%s(Signed) %" G_GINT64_MODIFIER "d", label, val);
5553     else
5554         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5555             ett_bacapp_tag, NULL, "%s - %u octets (Signed)", label, lvt);
5556     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5557
5558     return offset+tag_len+lvt;
5559 }
5560
5561 static guint
5562 fRealTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5563 {
5564     guint8      tag_no, tag_info;
5565     guint32     lvt;
5566     guint       tag_len;
5567     gfloat      f_val;
5568     proto_tree *subtree;
5569
5570     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5571     f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
5572     subtree = proto_tree_add_subtree_format(tree, tvb, offset, 4+tag_len,
5573         ett_bacapp_tag, NULL, "%s%f (Real)", label, f_val);
5574     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5575
5576     return offset+tag_len+4;
5577 }
5578
5579 static guint
5580 fDoubleTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5581 {
5582     guint8 tag_no, tag_info;
5583     guint32 lvt;
5584     guint tag_len;
5585     gdouble d_val;
5586     proto_tree *subtree;
5587
5588     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5589     d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
5590     subtree = proto_tree_add_subtree_format(tree, tvb, offset, 8+tag_len,
5591         ett_bacapp_tag, NULL, "%s%f (Double)", label, d_val);
5592     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5593
5594     return offset+tag_len+8;
5595 }
5596
5597 static guint
5598 fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5599 {
5600     guint32     val = 0, lvt;
5601     guint8      tag_no, tag_info;
5602     proto_item *ti;
5603     proto_tree *subtree;
5604     guint       tag_len;
5605
5606     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5607     if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
5608     {
5609         ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
5610             tvb, offset, lvt+tag_len, val);
5611         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5612     }
5613     else
5614     {
5615         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5616             ett_bacapp_tag, NULL, "Process Identifier - %u octets (Signed)", lvt);
5617     }
5618     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5619     offset += tag_len + lvt;
5620
5621     return offset;
5622 }
5623
5624 static guint
5625 fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5626 {
5627     guint32     val = 0, lvt;
5628     guint8      tag_no, tag_info;
5629     proto_tree *subtree;
5630     guint       tag_len;
5631
5632     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5633     if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
5634         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5635             ett_bacapp_tag, NULL,
5636             "%s (hh.mm.ss): %d.%02d.%02d%s",
5637             label,
5638             (val / 3600), ((val % 3600) / 60), (val % 60),
5639             val == 0 ? " (indefinite)" : "");
5640     else
5641         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5642             ett_bacapp_tag, NULL,
5643             "%s - %u octets (Signed)", label, lvt);
5644     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5645
5646     return offset+tag_len+lvt;
5647 }
5648
5649 static guint
5650 fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5651 {
5652     guint32     month, weekOfMonth, dayOfWeek;
5653     guint8      tag_no, tag_info;
5654     guint32     lvt;
5655     guint       tag_len;
5656     proto_tree *subtree;
5657
5658     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5659     month = tvb_get_guint8(tvb, offset+tag_len);
5660     weekOfMonth = tvb_get_guint8(tvb, offset+tag_len+1);
5661     dayOfWeek = tvb_get_guint8(tvb, offset+tag_len+2);
5662     subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5663                  ett_bacapp_tag, NULL, "%s %s, %s",
5664                  val_to_str(month, months, "month (%d) not found"),
5665                  val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"),
5666                  val_to_str(dayOfWeek, day_of_week, "day of week (%d) not found"));
5667     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5668
5669     return offset+tag_len+lvt;
5670 }
5671
5672 static guint
5673 fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5674 {
5675     guint32     year, month, day, weekday;
5676     guint8      tag_no, tag_info;
5677     guint32     lvt;
5678     guint       tag_len;
5679     proto_tree *subtree;
5680
5681     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5682     year    = tvb_get_guint8(tvb, offset+tag_len);
5683     month   = tvb_get_guint8(tvb, offset+tag_len+1);
5684     day     = tvb_get_guint8(tvb, offset+tag_len+2);
5685     weekday = tvb_get_guint8(tvb, offset+tag_len+3);
5686     if ((year == 255) && (day == 255) && (month == 255) && (weekday == 255)) {
5687         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5688             ett_bacapp_tag, NULL,
5689             "%sany", label);
5690     }
5691     else if (year != 255) {
5692         year += 1900;
5693         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5694             ett_bacapp_tag, NULL,
5695             "%s%s %d, %d, (Day of Week = %s)",
5696             label, val_to_str(month,
5697                 months,
5698                 "month (%d) not found"),
5699             day, year, val_to_str(weekday,
5700                 day_of_week,
5701                 "(%d) not found"));
5702     } else {
5703         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5704             ett_bacapp_tag, NULL,
5705             "%s%s %d, any year, (Day of Week = %s)",
5706             label, val_to_str(month, months, "month (%d) not found"),
5707             day, val_to_str(weekday, day_of_week, "(%d) not found"));
5708     }
5709     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5710
5711     return offset+tag_len+lvt;
5712 }
5713
5714 static guint
5715 fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5716 {
5717     guint32     hour, minute, second, msec, lvt;
5718     guint8      tag_no, tag_info;
5719     guint       tag_len;
5720     proto_tree *subtree;
5721
5722     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5723     hour    = tvb_get_guint8(tvb, offset+tag_len);
5724     minute  = tvb_get_guint8(tvb, offset+tag_len+1);
5725     second  = tvb_get_guint8(tvb, offset+tag_len+2);
5726     msec    = tvb_get_guint8(tvb, offset+tag_len+3);
5727     if ((hour == 255) && (minute == 255) && (second == 255) && (msec == 255))
5728         subtree = proto_tree_add_subtree_format(tree, tvb, offset,
5729             lvt+tag_len, ett_bacapp_tag, NULL,
5730             "%sany", label);
5731     else
5732         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
5733             ett_bacapp_tag, NULL,
5734             "%s%d:%02d:%02d.%d %s = %02d:%02d:%02d.%d",
5735             label,
5736             hour > 12 ? hour - 12 : hour,
5737             minute, second, msec,
5738             hour >= 12 ? "P.M." : "A.M.",
5739             hour, minute, second, msec);
5740     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5741
5742     return offset+tag_len+lvt;
5743 }
5744
5745 static guint
5746 fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5747 {
5748     proto_tree *subtree = tree;
5749
5750     if (label != NULL) {
5751         subtree = proto_tree_add_subtree(subtree, tvb, offset, 10, ett_bacapp_value, NULL, label);
5752     }
5753     offset = fDate(tvb, pinfo, subtree, offset, "Date: ");
5754     return fTime(tvb, pinfo, subtree, offset, "Time: ");
5755 }
5756
5757 static guint
5758 fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5759 {
5760     guint lastoffset = 0;
5761     guint8 tag_no, tag_info;
5762     guint32 lvt;
5763
5764     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
5765         lastoffset = offset;
5766         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5767         if (tag_is_closing(tag_info)) {   /* closing Tag, but not for me */
5768             return offset;
5769         }
5770         offset = fTime(tvb, pinfo, tree, offset, "Time: ");
5771         offset = fApplicationTypes(tvb, pinfo, tree, offset, "Value: ");
5772
5773         if (offset == lastoffset) break;    /* exit loop if nothing happens inside */
5774     }
5775     return offset;
5776 }
5777
5778 static guint
5779 fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5780 {
5781     guint8  tag_no, tag_info;
5782     guint32 lvt;
5783
5784     switch (fTagNo(tvb, offset)) {
5785     case 0: /* Date */
5786         offset = fDate(tvb, pinfo, tree, offset, "Date: ");
5787         break;
5788     case 1: /* dateRange */
5789         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5790         offset  = fDateRange(tvb, pinfo, tree, offset);
5791         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5792         break;
5793     case 2: /* BACnetWeekNDay */
5794         offset = fWeekNDay(tvb, pinfo, tree, offset);
5795         break;
5796     default:
5797         return offset;
5798     }
5799
5800     return offset;
5801 }
5802
5803 static guint
5804 fEventTimeStamps( tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
5805 {
5806     guint32     lvt     = 0;
5807     proto_tree* subtree = tree;
5808
5809     if (tvb_reported_length_remaining(tvb, offset) > 0) {
5810         subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventTimeStamps");
5811
5812         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
5813         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
5814         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
5815     }
5816     return offset;
5817 }
5818
5819 static guint
5820 fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5821 {
5822     guint8  tag_no = 0, tag_info = 0;
5823     guint32 lvt    = 0;
5824
5825     if (tvb_reported_length_remaining(tvb, offset) > 0) {   /* don't loop, it's a CHOICE */
5826         switch (fTagNo(tvb, offset)) {
5827         case 0: /* time */
5828             offset = fTime(tvb, pinfo, tree, offset, label?label:"time: ");
5829             break;
5830         case 1: /* sequenceNumber */
5831             offset = fUnsignedTag(tvb, pinfo, tree, offset,
5832                 label?label:"sequence number: ");
5833             break;
5834         case 2: /* dateTime */
5835             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5836             offset  = fDateTime(tvb, pinfo, tree, offset, label?label:"date time: ");
5837             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5838             break;
5839         default:
5840             return offset;
5841         }
5842     }
5843
5844     return offset;
5845 }
5846
5847
5848 static guint
5849 fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5850 {
5851     if (tvb_reported_length_remaining(tvb, offset) > 0) {
5852         offset = fApplicationTypes(tvb, pinfo, tree, offset, "increment: ");
5853     }
5854     return offset;
5855 }
5856
5857 static const value_string
5858 BACnetDaysOfWeek [] = {
5859     { 0, "Monday" },
5860     { 1, "Tuesday" },
5861     { 2, "Wednesday" },
5862     { 3, "Thursday" },
5863     { 4, "Friday" },
5864     { 5, "Saturday" },
5865     { 6, "Sunday" },
5866     { 0, NULL }
5867 };
5868
5869 static guint
5870 fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5871 {
5872     if (tvb_reported_length_remaining(tvb, offset) > 0) {
5873         offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
5874                                              "valid Days: ", BACnetDaysOfWeek);
5875         offset = fTime(tvb, pinfo, tree, offset, "from time: ");
5876         offset = fTime(tvb, pinfo, tree, offset, "to time: ");
5877         offset = fRecipient(tvb, pinfo, tree, offset);
5878         offset = fProcessId(tvb, pinfo, tree, offset);
5879         offset = fApplicationTypes(tvb, pinfo, tree, offset,
5880                                     "issue confirmed notifications: ");
5881         offset = fBitStringTagVS(tvb, pinfo, tree, offset,
5882                                   "transitions: ", BACnetEventTransitionBits);
5883     }
5884     return offset;
5885 }
5886
5887
5888 static guint
5889 fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
5890 {
5891     gchar      *tmp;
5892     guint       start   = offset;
5893     guint8      tag_no, tag_info;
5894     proto_tree *subtree = tree;
5895
5896     offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5897
5898     if (lvt > 0) {
5899         tmp = tvb_bytes_to_str(wmem_packet_scope(), tvb, offset, lvt);
5900         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt,
5901                     ett_bacapp_tag, NULL, "%s %s", label, tmp);
5902         offset += lvt;
5903     }
5904
5905     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
5906
5907     return offset;
5908 }
5909
5910 static guint
5911 fMacAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
5912 {
5913     guint start = offset;
5914     guint8 tag_no, tag_info;
5915     proto_tree* subtree = tree;
5916
5917     offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5918
5919     /* just add the label, with the tagHeader information in its subtree */
5920     subtree = proto_tree_add_subtree(tree, tvb, offset, 6, ett_bacapp_tag, NULL, label);
5921
5922     if (lvt == 6) { /* we have 6 Byte IP Address with 4 Octets IPv4 and 2 Octets Port Information */
5923         proto_tree_add_item(tree, hf_bacapp_tag_IPV4, tvb, offset, 4, ENC_BIG_ENDIAN);
5924         proto_tree_add_item(tree, hf_bacapp_tag_PORT, tvb, offset+4, 2, ENC_BIG_ENDIAN);
5925     } else if (lvt == 18) { /* we have 18 Byte IP Address with 16 Octets IPv6 and 2 Octets Port Information */
5926         proto_tree_add_item(tree, hf_bacapp_tag_IPV6, tvb, offset, 16, ENC_NA);
5927         proto_tree_add_item(tree, hf_bacapp_tag_PORT, tvb, offset+16, 2, ENC_BIG_ENDIAN);
5928     } else { /* we have 1 Byte MS/TP Address or anything else interpreted as an address */
5929         subtree = proto_tree_add_subtree(tree, tvb, offset, lvt,
5930                 ett_bacapp_tag, NULL, tvb_bytes_to_str(wmem_packet_scope(), tvb, offset, lvt));
5931     }
5932     offset += lvt;
5933
5934     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
5935
5936     return offset;
5937 }
5938
5939 static guint
5940 fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5941 {
5942     guint8  tag_no, tag_info;
5943     guint32 lvt;
5944     guint   offs;
5945
5946     offset = fUnsignedTag(tvb, pinfo, tree, offset, "network-number");
5947     offs   = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5948     if (lvt == 0) {
5949         proto_tree_add_text(tree, tvb, offset, offs, "MAC-address: broadcast");
5950         offset += offs;
5951     } else
5952         offset  = fMacAddress(tvb, pinfo, tree, offset, "MAC-address: ", lvt);
5953
5954     return offset;
5955 }
5956
5957 static guint
5958 fSessionKey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5959 {
5960     offset = fOctetString(tvb, pinfo, tree, offset, "session key: ", 8);
5961     return fAddress(tvb, pinfo, tree, offset);
5962 }
5963
5964 static guint
5965 fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5966 {
5967     guint8      tag_no, tag_info;
5968     guint32     lvt;
5969     guint       tag_length;
5970     proto_tree *subtree;
5971     guint32     object_id;
5972
5973     tag_length  = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5974     object_id   = tvb_get_ntohl(tvb, offset+tag_length);
5975     object_type = object_id_type(object_id);
5976     subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_length + 4,
5977         ett_bacapp_tag, NULL, "ObjectIdentifier: %s, %u",
5978         val_to_split_str(object_type,
5979             128,
5980             BACnetObjectType,
5981             ASHRAE_Reserved_Fmt,
5982             Vendor_Proprietary_Fmt),
5983         object_id_instance(object_id));
5984
5985     if (col_get_writable(pinfo->cinfo))
5986         col_append_fstr(pinfo->cinfo, COL_INFO, "%s,%u ",
5987             val_to_split_str(object_type,
5988                 128,
5989                 BACnetObjectType,
5990                 ASHRAE_Reserved_Fmt,
5991                 Vendor_Proprietary_Fmt),
5992                 object_id_instance(object_id));
5993
5994     /* update BACnet Statistics */
5995     updateBacnetInfoValue(BACINFO_OBJECTID,
5996                   wmem_strdup(wmem_packet_scope(),
5997                     val_to_split_str(object_type, 128,
5998                     BACnetObjectType, ASHRAE_Reserved_Fmt,
5999                     Vendor_Proprietary_Fmt)));
6000     updateBacnetInfoValue(BACINFO_INSTANCEID,
6001                   wmem_strdup_printf(wmem_packet_scope(),
6002                     "Instance ID: %u",
6003                     object_id_instance(object_id)));
6004
6005     /* here are the details of how we arrived at the above text */
6006     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6007     offset += tag_length;
6008     proto_tree_add_item(subtree, hf_bacapp_objectType, tvb, offset, 4, ENC_BIG_ENDIAN);
6009     proto_tree_add_item(subtree, hf_bacapp_instanceNumber, tvb, offset, 4, ENC_BIG_ENDIAN);
6010     offset += 4;
6011
6012     return offset;
6013 }
6014
6015 static guint
6016 fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6017 {
6018     guint8  tag_no, tag_info;
6019     guint32 lvt;
6020
6021     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6022     if (tag_no < 2) {
6023         if (tag_no == 0) { /* device */
6024             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
6025         }
6026         else {  /* address */
6027             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6028             offset  = fAddress(tvb, pinfo, tree, offset);
6029             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6030         }
6031     }
6032     return offset;
6033 }
6034
6035 static guint
6036 fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6037 {
6038     guint       lastoffset = 0;
6039     guint8      tag_no, tag_info;
6040     guint32     lvt;
6041     proto_tree *orgtree    = tree;
6042     proto_tree *subtree;
6043
6044     /* beginning of new item - indent and label */
6045     tree = proto_tree_add_subtree(orgtree, tvb, offset, 1, ett_bacapp_value, NULL, "Recipient Process" );
6046
6047     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6048         lastoffset = offset;
6049
6050         switch (fTagNo(tvb, offset)) {
6051         case 0: /* recipient */
6052             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
6053             subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "Recipient");    /* add tree label and indent */
6054             offset  = fRecipient(tvb, pinfo, subtree, offset);
6055             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
6056             break;
6057         case 1: /* processId */
6058             offset = fProcessId(tvb, pinfo, tree, offset);
6059             lastoffset = offset;
6060             break;
6061         default:
6062             break;
6063         }
6064         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6065     }
6066     return offset;
6067 }
6068
6069 static guint
6070 fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6071 {
6072     guint       lastoffset = 0;
6073     guint8      tag_no, tag_info;
6074     guint32     lvt;
6075     proto_tree *subtree;
6076     proto_tree *orgtree    = tree;
6077     guint       itemno     = 1;
6078
6079     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6080         lastoffset = offset;
6081         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6082         if (tag_is_closing(tag_info) ) {
6083             return offset;
6084         }
6085         switch (tag_no) {
6086
6087         case 0: /* recipient */
6088                 /* beginning of new item in list */
6089                 tree = proto_tree_add_subtree_format(orgtree, tvb, offset, 1,
6090                     ett_bacapp_value, NULL, "Subscription %d",itemno);    /* add tree label and indent */
6091                 itemno = itemno + 1;
6092
6093                 subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
6094                     ett_bacapp_value, NULL, "Recipient");    /* add tree label and indent */
6095                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
6096                 offset  = fRecipientProcess(tvb, pinfo, subtree, offset);
6097                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);  /* show context close */
6098             break;
6099         case 1: /* MonitoredPropertyReference */
6100                 subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
6101                     ett_bacapp_value, NULL, "Monitored Property Reference");
6102                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6103                 offset  = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
6104                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6105             break;
6106         case 2: /* IssueConfirmedNotifications - boolean */
6107             offset = fBooleanTag(tvb, pinfo, tree, offset, "Issue Confirmed Notifications: ");
6108             break;
6109         case 3: /* TimeRemaining */
6110             offset = fUnsignedTag(tvb, pinfo, tree, offset, "Time Remaining: ");
6111             break;
6112         case 4: /* COVIncrement */
6113             offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
6114             break;
6115         default:
6116             break;
6117         }
6118         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6119     }
6120     return offset;
6121 }
6122
6123 static guint
6124 fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6125 {
6126     offset = fObjectIdentifier(tvb, pinfo, tree, offset);
6127     return fAddress(tvb, pinfo, tree, offset);
6128 }
6129
6130 static guint
6131 fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match)
6132 {
6133     guint       lastoffset = 0, len;
6134     guint8      tag_no, tag_info;
6135     guint32     lvt;
6136     proto_tree *subtree    = tree;
6137
6138     /* set the optional global properties to indicate not-used */
6139     propertyArrayIndex = -1;
6140     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6141         lastoffset = offset;
6142         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6143         if (tag_is_closing(tag_info) ) {
6144             if (tag_no == tag_match) {
6145                 return offset;
6146             }
6147             offset += len;
6148             subtree = tree;
6149             continue;
6150         }
6151         switch (tag_no) {
6152
6153         case 0: /* deviceIdentifier */
6154             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
6155             break;
6156         case 1: /* objectIdentifier */
6157             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
6158             break;
6159         case 2: /* propertyIdentifier */
6160             offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
6161             break;
6162         case 3: /* propertyArrayIndex */
6163             offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
6164             break;
6165         case 4: /* propertyValue */
6166             offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
6167             break;
6168         case 5: /* priority */
6169             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
6170             break;
6171         case 6: /* postDelay */
6172             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Post Delay: ");
6173             break;
6174         case 7: /* quitOnFailure */
6175             offset = fBooleanTag(tvb, pinfo, subtree, offset,
6176                 "Quit On Failure: ");
6177             break;
6178         case 8: /* writeSuccessful */
6179             offset = fBooleanTag(tvb, pinfo, subtree, offset,
6180                 "Write Successful: ");
6181             break;
6182         default:
6183             return offset;
6184         }
6185         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6186     }
6187     return offset;
6188 }
6189
6190 /* BACnetActionList ::= SEQUENCE{
6191       action [0] SEQUENCE OF BACnetActionCommand
6192       }
6193 */
6194 static guint
6195 fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6196 {
6197     guint       lastoffset = 0, len;
6198     guint8      tag_no, tag_info;
6199     guint32     lvt;
6200     proto_tree *subtree    = tree;
6201
6202     while (tvb_reported_length_remaining(tvb, offset) > 0) {
6203         lastoffset = offset;
6204         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6205         if (tag_is_closing(tag_info)) {
6206             subtree = tree;
6207             if ( tag_no != 0 ) /* don't eat the closing property tag, just return */
6208                 return offset;
6209             offset += len;
6210             continue;
6211         }
6212         if (tag_is_opening(tag_info)) {
6213             subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "Action List");
6214             offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
6215                 &tag_no, &tag_info, &lvt);
6216         }
6217         switch (tag_no) {
6218         case 0: /* BACnetActionCommand */
6219             offset = fActionCommand(tvb, pinfo, subtree, offset, tag_no);
6220             break;
6221         default:
6222             break;
6223         }
6224         if (offset == lastoffset) break;    /* nothing happened, exit loop */
6225     }
6226     return offset;
6227 }
6228
6229 static guint
6230 fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6231 {
6232     guint8       tag_no, tag_info;
6233     guint32      lvt;
6234     guint        tag_len;
6235     proto_tree  *subtree;
6236     const gchar *label = "Property Identifier";
6237
6238     propertyIdentifier = 0; /* global Variable */
6239     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6240     /* can we decode this value? */
6241     if (fUnsigned32(tvb, offset+tag_len, lvt, (guint32 *)&propertyIdentifier)) {
6242         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6243             ett_bacapp_tag, NULL,
6244             "%s: %s (%u)", label,
6245             val_to_split_str(propertyIdentifier, 512,
6246                 BACnetPropertyIdentifier,
6247                 ASHRAE_Reserved_Fmt,
6248                 Vendor_Proprietary_Fmt), propertyIdentifier);
6249         if (col_get_writable(pinfo->cinfo))
6250             col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
6251                 val_to_split_str(propertyIdentifier, 512,
6252                     BACnetPropertyIdentifier,
6253                     ASHRAE_Reserved_Fmt,
6254                     Vendor_Proprietary_Fmt));
6255     } else {
6256         /* property identifiers cannot be larger than 22-bits */
6257         return offset;
6258     }
6259
6260     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6261     proto_tree_add_item(subtree, hf_BACnetPropertyIdentifier, tvb,
6262         offset+tag_len, lvt, ENC_BIG_ENDIAN);
6263
6264     return offset+tag_len+lvt;
6265 }
6266
6267 static guint
6268 fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6269 {
6270     guint8      tag_no, tag_info;
6271     guint32     lvt;
6272     guint       tag_len;
6273     proto_tree *subtree;
6274
6275     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6276     if (fUnsigned32(tvb, offset + tag_len, lvt, (guint32 *)&propertyArrayIndex))
6277         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6278             ett_bacapp_tag, NULL, "property Array Index (Unsigned) %u", propertyArrayIndex);
6279     else
6280         subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6281             ett_bacapp_tag, NULL, "property Array Index - %u octets (Unsigned)", lvt);
6282     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6283
6284     return offset+tag_len+lvt;
6285 }
6286
6287 static guint
6288 fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6289 {
6290     guint8      tag_no, tag_info, character_set;
6291     guint32     lvt, l;
6292     guint       offs;
6293     const char *coding;
6294     guint8     *out;
6295     proto_tree *subtree;
6296     guint       start = offset;
6297
6298     if (tvb_reported_length_remaining(tvb, offset) > 0) {
6299
6300         offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6301         offset += offs;
6302
6303         character_set = tvb_get_guint8(tvb, offset);
6304         offset++;
6305         lvt--;
6306
6307         /* Account for code page if DBCS */
6308         if (character_set == IBM_MS_DBCS) {
6309             offset += 2;
6310             lvt -= 2;
6311         }
6312
6313         do {
6314             l = MIN(lvt, 256);
6315             /*
6316              * XXX - are we guaranteed that these encoding
6317              * names correspond, on *all* platforms with
6318              * iconv(), to the encodings we want?
6319              * If not (and perhaps even if so), we should
6320              * perhaps have our own iconv() implementation,
6321              * with a different name, so that we control the
6322              * encodings it supports and the names of those
6323              * encodings.
6324              *
6325              * We should also handle that in the general
6326              * string handling code, rather than making it
6327              * specific to the BACAPP dissector, as many
6328              * other dissectors need to handle various
6329              * character encodings.
6330              */
6331             /** this decoding may be not correct for multi-byte characters, Lka */
6332             switch (character_set) {
6333             case ANSI_X3_4:
6334                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_UTF_8);
6335                 coding = "UTF-8";
6336                 break;
6337             case IBM_MS_DBCS:
6338                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_ASCII);
6339                 coding = "IBM MS DBCS";
6340                 break;
6341             case JIS_C_6226:
6342                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_ASCII);
6343                 coding = "JIS C 6226";
6344                 break;
6345             case ISO_10646_UCS4:
6346                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_UCS_4|ENC_BIG_ENDIAN);
6347                 coding = "ISO 10646 UCS-4";
6348                 break;
6349             case ISO_10646_UCS2:
6350                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_UCS_2|ENC_BIG_ENDIAN);
6351                 coding = "ISO 10646 UCS-2";
6352                 break;
6353             case ISO_8859_1:
6354                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_ISO_8859_1);
6355                 coding = "ISO 8859-1";
6356                 break;
6357             default:
6358                 /* Assume this is some form of extended ASCII, with one-byte code points for ASCII characters */
6359                 out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_ASCII);
6360                 coding = "unknown";
6361                 break;
6362             }
6363             subtree = proto_tree_add_subtree_format(tree, tvb, offset, l, ett_bacapp_tag, NULL,
6364                                         "%s%s '%s'", label, coding, out);
6365             lvt    -= l;
6366             offset += l;
6367         } while (lvt > 0);
6368
6369         fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6370         proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, ENC_BIG_ENDIAN);
6371
6372         if (character_set == IBM_MS_DBCS) {
6373             proto_tree_add_item(subtree, hf_BACnetCodePage, tvb, start+offs+1, 2, ENC_BIG_ENDIAN);
6374         }
6375         /* XXX - put the string value here */
6376     }
6377     return offset;
6378 }
6379
6380 static guint
6381 fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label,
6382     const value_string *src)
6383 {
6384     guint8      tag_no, tag_info, tmp;
6385     gint        j, unused, skip;
6386     guint       start = offset;
6387     guint       offs;
6388     guint32     lvt, i, numberOfBytes;
6389     guint8      bf_arr[256];
6390     proto_tree* subtree = tree;
6391
6392     offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6393     numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
6394     offset += offs;
6395     unused  = tvb_get_guint8(tvb, offset); /* get the unused Bits */
6396     subtree = proto_tree_add_subtree_format(tree, tvb, start, offs+lvt,
6397                                   ett_bacapp_tag, NULL,
6398                                   "%s(Bit String)", label);
6399
6400     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6401     proto_tree_add_text(subtree, tvb, offset, 1,
6402                 "Unused bits: %u", unused);
6403     memset(bf_arr, 0, 256);
6404     skip = 0;
6405     for (i = 0; i < numberOfBytes; i++) {
6406         tmp = tvb_get_guint8(tvb, (offset)+i+1);
6407         if (i == numberOfBytes-1) { skip = unused; }
6408         for (j = 0; j < 8-skip; j++) {
6409             if (src != NULL) {
6410                 if (tmp & (1 << (7 - j)))
6411                     proto_tree_add_text(subtree, tvb,
6412                         offset+i+1, 1,
6413                         "%s = TRUE",
6414                         val_to_str((guint) (i*8 +j),
6415                             src,
6416                             ASHRAE_Reserved_Fmt));
6417                 else
6418                     proto_tree_add_text(subtree, tvb,
6419                         offset+i+1, 1,
6420                         "%s = FALSE",
6421                         val_to_str((guint) (i*8 +j),
6422                             src,
6423                             ASHRAE_Reserved_Fmt));
6424             } else {
6425                 bf_arr[MIN(255, (i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
6426             }
6427         }
6428     }
6429
6430     if (src == NULL) {
6431         bf_arr[MIN(255, numberOfBytes*8-unused)] = 0;
6432         proto_tree_add_text(subtree, tvb, offset, lvt, "B'%s'", bf_arr);
6433     }
6434
6435     offset += lvt;
6436
6437     return offset;
6438 }
6439
6440 static guint
6441 fBitStringTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6442 {
6443     return fBitStringTagVS(tvb, pinfo, tree, offset, label, NULL);
6444 }
6445
6446 /* handles generic application types, as well as enumerated and enumerations
6447    with reserved and proprietarty ranges (split) */
6448 static guint
6449 fApplicationTypesEnumeratedSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
6450     const gchar *label, const value_string *src, guint32 split_val)
6451 {
6452     guint8  tag_no, tag_info;
6453     guint32 lvt;
6454     guint   tag_len;
6455
6456     if (tvb_reported_length_remaining(tvb, offset) > 0) {
6457
6458         tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6459         if (!tag_is_context_specific(tag_info)) {
6460             switch (tag_no) {
6461             case 0: /** NULL 20.2.2 */
6462                 offset = fNullTag(tvb, pinfo, tree, offset, label);
6463                 break;
6464             case 1: /** BOOLEAN 20.2.3 */
6465                 offset = fBooleanTag(tvb, pinfo, tree, offset, label);
6466                 break;
6467             case 2: /** Unsigned Integer 20.2.4 */
6468                 offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
6469                 break;
6470             case 3: /** Signed Integer 20.2.5 */
6471                 offset = fSignedTag(tvb, pinfo, tree, offset, label);
6472                 break;
6473             case 4: /** Real 20.2.6 */
6474                 offset = fRealTag(tvb, pinfo, tree, offset, label);
6475                 break;
6476             case 5: /** Double 20.2.7 */
6477                 offset = fDoubleTag(tvb, pinfo, tree, offset, label);
6478                 break;
6479             case 6: /** Octet String 20.2.8 */
6480                 offset = fOctetString(tvb, pinfo, tree, offset, label, lvt);
6481                 break;
6482             case 7: /** Character String 20.2.9 */
6483                 offset = fCharacterString(tvb, pinfo, tree, offset, label);
6484                 break;
6485             case 8: /** Bit String 20.2.10 */
6486                 offset = fBitStringTagVS(tvb, pinfo, tree, offset, label, src);
6487                 break;
6488             case 9: /** Enumerated 20.2.11 */
6489                 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, src, split_val);
6490                 break;
6491             case 10: /** Date 20.2.12 */
6492                 offset = fDate(tvb, pinfo, tree, offset, label);
6493                 break;
6494             case 11: /** Time 20.2.13 */
6495                 offset = fTime(tvb, pinfo, tree, offset, label);
6496                 break;
6497             case 12: /** BACnetObjectIdentifier 20.2.14 */
6498                 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
6499                 break;
6500             case 13: /* reserved for ASHRAE */
6501             case 14:
6502             case 15:
6503                 proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s'reserved for ASHRAE'", label);
6504                 offset += lvt + tag_len;
6505                 break;
6506             default:
6507                 break;
6508             }
6509
6510         }
6511     }
6512     return offset;
6513 }
6514
6515 static guint
6516 fShedLevel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6517 {
6518     guint lastoffset = 0;
6519
6520     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6521         lastoffset = offset;
6522
6523         switch (fTagNo(tvb, offset)) {
6524         case 0: /* percent */
6525             offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed percent: ");
6526             break;
6527         case 1: /* level */
6528             offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed level: ");
6529             break;
6530         case 2: /* amount */
6531             offset = fRealTag(tvb, pinfo, tree, offset, "shed amount: ");
6532             break;
6533         default:
6534             return offset;
6535         }
6536         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6537     }
6538     return offset;
6539 }
6540
6541 static guint
6542 fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
6543     const gchar *label, const value_string *vs)
6544 {
6545     return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, vs, 0);
6546 }
6547
6548 static guint
6549 fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
6550     const gchar *label)
6551 {
6552     return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, NULL, 0);
6553 }
6554
6555 static guint
6556 fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6557 {
6558     guint8      tag_no, tag_info;
6559     guint32     lvt;
6560     guint       tag_len;
6561     proto_tree *subtree;
6562     gint        tvb_len;
6563
6564     (void)label;
6565     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6566     /* cap the the suggested length in case of bad data */
6567     tvb_len = tvb_reported_length_remaining(tvb, offset+tag_len);
6568     if ((tvb_len >= 0) && ((guint32)tvb_len < lvt)) {
6569         lvt = tvb_len;
6570     }
6571     subtree = proto_tree_add_subtree_format(tree, tvb, offset+tag_len, lvt,
6572         ett_bacapp_tag, NULL, "Context Value (as %u DATA octets)", lvt);
6573
6574     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6575
6576     return offset + tag_len + lvt;
6577 }
6578 /*
6579 BACnetPrescale ::= SEQUENCE {
6580     multiplier  [0] Unsigned,
6581 moduloDivide    [1] Unsigned
6582 }
6583 */
6584 static guint
6585 fPrescale(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
6586 {
6587     guint8  tag_no, tag_info;
6588     guint32 lvt;
6589     guint   lastoffset = 0;
6590
6591     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6592         lastoffset = offset;
6593         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6594         if (tag_is_closing(tag_info) ) {
6595             return offset;
6596             }
6597         switch (tag_no) {
6598         case 0: /* multiplier */
6599             offset = fUnsignedTag(tvb, pinfo, tree, offset, "Multiplier: ");
6600             break;
6601         case 1: /* moduloDivide */
6602             offset = fUnsignedTag(tvb, pinfo, tree, offset, "Modulo Divide: ");
6603             break;
6604         default:
6605             return offset;
6606         }
6607         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6608     }
6609     return offset;
6610
6611 }
6612 /*
6613 BACnetScale ::= CHOICE {
6614     floatScale  [0] REAL,
6615 integerScale    [1] INTEGER
6616 }
6617 */
6618 static guint
6619 fScale(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
6620 {
6621     guint8  tag_no, tag_info;
6622     guint32 lvt;
6623     guint   lastoffset = 0;
6624
6625     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6626         lastoffset = offset;
6627         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6628         if (tag_is_closing(tag_info) ) {
6629             return offset;
6630             }
6631         switch (tag_no) {
6632         case 0: /* floatScale */
6633             offset = fRealTag(tvb, pinfo, tree, offset, "Float Scale: ");
6634             break;
6635         case 1: /* integerScale */
6636             offset = fSignedTag(tvb, pinfo, tree, offset, "Integer Scale: ");
6637             break;
6638         default:
6639             return offset;
6640         }
6641         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6642     }
6643     return offset;
6644 }
6645 /*
6646 BACnetAccumulatorRecord ::= SEQUENCE {
6647     timestamp       [0] BACnetDateTime,
6648     presentValue        [1] Unsigned,
6649     accumulatedValue    [2] Unsigned,
6650     accumulatortStatus  [3] ENUMERATED {
6651                     normal          (0),
6652                     starting        (1),
6653                     recovered       (2),
6654                     abnormal        (3),
6655                     failed          (4)
6656                     }
6657 }
6658 */
6659 static guint
6660 fLoggingRecord(tvbuff_t *tvb, packet_info *pinfo  _U_, proto_tree *tree, guint offset)
6661 {
6662     guint8  tag_no, tag_info;
6663     guint32 lvt;
6664     guint   lastoffset = 0;
6665
6666     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6667         lastoffset = offset;
6668         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6669         if (tag_is_closing(tag_info) ) {
6670             return offset;
6671             }
6672         switch (tag_no) {
6673         case 0: /* timestamp */
6674             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6675             offset  = fDateTime(tvb, pinfo, tree, offset, "Timestamp: ");
6676             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6677             break;
6678         case 1: /* presentValue */
6679             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Present Value: ");
6680             break;
6681         case 2: /* accumulatedValue */
6682             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Accumulated Value: ");
6683             break;
6684         case 3: /* accumulatorStatus */
6685             offset  = fEnumeratedTag(tvb, pinfo, tree, offset, "Accumulator Status: ", BACnetAccumulatorStatus);
6686             break;
6687         default:
6688             return offset;
6689         }
6690         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6691     }
6692     return offset;
6693 }
6694
6695 /*
6696  SEQ OF Any enumeration (current usage is SEQ OF BACnetDoorAlarmState
6697 */
6698 static guint
6699 fSequenceOfEnums(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, const value_string *vs)
6700 {
6701     guint8  tag_no, tag_info;
6702     guint32 lvt;
6703     guint   lastoffset = 0;
6704
6705     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6706         lastoffset = offset;
6707         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6708         if (tag_is_closing(tag_info) ) {
6709             return offset;
6710             }
6711         offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, label, vs);
6712         if ( offset == lastoffset ) break;
6713     }
6714     return offset;
6715 }
6716
6717 /*
6718 SEQ OF BACnetDeviceObjectReference (accessed as an array)
6719 }
6720 */
6721 static guint
6722 fDoorMembers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6723 {
6724     guint8  tag_no, tag_info;
6725     guint32 lvt;
6726     guint   lastoffset = 0;
6727
6728     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6729         lastoffset = offset;
6730         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6731         if (tag_is_closing(tag_info) ) {
6732             return offset;
6733             }
6734         offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
6735         if (offset == lastoffset) break;
6736     }
6737     return offset;
6738 }
6739
6740 /*
6741 SEQ OF ReadAccessSpecification
6742 */
6743 static guint
6744 fListOfGroupMembers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6745 {
6746     guint8  tag_no, tag_info;
6747     guint32 lvt;
6748     guint   lastoffset = 0;
6749
6750     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6751         lastoffset = offset;
6752         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6753         if (tag_is_closing(tag_info) ) {
6754             return offset;
6755             }
6756         offset = fReadAccessSpecification(tvb, pinfo, tree, offset);
6757         if ( offset == lastoffset ) break;
6758     }
6759     return offset;
6760 }
6761
6762 static guint
6763 fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6764 {
6765     guint8  tag_no, tag_info;
6766     guint32 lvt;
6767     guint   lastoffset = 0, depth = 0;
6768     char    ar[256];
6769     guint32 save_object_type;
6770
6771     if (propertyIdentifier >= 0) {
6772         g_snprintf(ar, sizeof(ar), "%s: ",
6773             val_to_split_str(propertyIdentifier, 512,
6774                 BACnetPropertyIdentifier,
6775                 ASHRAE_Reserved_Fmt,
6776                 Vendor_Proprietary_Fmt));
6777     } else {
6778         g_snprintf(ar, sizeof(ar), "Abstract Type: ");
6779     }
6780     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6781         lastoffset = offset;
6782         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6783         if (tag_is_closing(tag_info)) { /* closing tag, but not for me */
6784             if (depth <= 0) return offset;
6785         }
6786
6787         /* Application Tags */
6788         switch (propertyIdentifier) {
6789         case 2: /* action */
6790             /* loop object is application tagged,
6791                 command object is context tagged */
6792             if (tag_is_context_specific(tag_info)) {
6793                 /* BACnetActionList */
6794                 offset = fActionList(tvb, pinfo, tree, offset);
6795             } else {
6796                 /* BACnetAction */
6797                 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6798                     BACnetAction);
6799             }
6800             break;
6801         case 30: /* BACnetAddressBinding */
6802             offset = fAddressBinding(tvb, pinfo, tree, offset);
6803             break;
6804         case 54: /* list of object property reference */
6805             offset = fLOPR(tvb, pinfo, tree, offset);
6806             break;
6807         case 55: /* list-of-session-keys */
6808             fSessionKey(tvb, pinfo, tree, offset);
6809             break;
6810         case 79: /* object-type */
6811         case 96: /* protocol-object-types-supported */
6812             offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar,
6813                 BACnetObjectType, 128);
6814             break;
6815         case 97: /* Protocol-Services-Supported */
6816             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6817                 BACnetServicesSupported);
6818             break;
6819         case 102: /* recipient-list */
6820             offset = fDestination(tvb, pinfo, tree, offset);
6821             break;
6822         case 107: /* segmentation-supported */
6823             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6824                 BACnetSegmentation);
6825             break;
6826         case 111: /* Status-Flags */
6827             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6828                 BACnetStatusFlags);
6829             break;
6830         case 112: /* System-Status */
6831             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6832                 BACnetDeviceStatus);
6833             break;
6834         case 117: /* units */
6835             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6836                 BACnetEngineeringUnits);
6837             break;
6838         case 87:    /* priority-array -- accessed as a BACnetARRAY */
6839             if (propertyArrayIndex == 0) {
6840                 /* BACnetARRAY index 0 refers to the length
6841                 of the array, not the elements of the array */
6842                 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6843             } else {
6844                 offset = fPriorityArray(tvb, pinfo, tree, offset);
6845             }
6846             break;
6847         case 38:    /* exception-schedule */
6848             if (object_type < 128) {
6849                 if (propertyArrayIndex == 0) {
6850                     /* BACnetARRAY index 0 refers to the length
6851                     of the array, not the elements of the array */
6852                     offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6853                 } else {
6854                     offset = fSpecialEvent(tvb, pinfo, tree, offset);
6855                 }
6856             }
6857             break;
6858         case 19:  /* controlled-variable-reference */
6859         case 60:  /* manipulated-variable-reference */
6860         case 132: /* log-device-object-property */
6861             offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
6862             break;
6863         case 109: /* Setpoint-Reference */
6864             /* setpoint-Reference is actually BACnetSetpointReference which is a SEQ of [0] */
6865             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6866             offset = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
6867             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6868             break;
6869         case 123:   /* weekly-schedule -- accessed as a BACnetARRAY */
6870             if (object_type < 128) {
6871                 if (propertyArrayIndex == 0) {
6872                     /* BACnetARRAY index 0 refers to the length
6873                     of the array, not the elements of the array */
6874                     offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6875                 } else {
6876                     offset = fWeeklySchedule(tvb, pinfo, tree, offset);
6877                 }
6878             }
6879             break;
6880         case 127:   /* client COV increment */
6881             offset = fClientCOV(tvb, pinfo, tree, offset);
6882             break;
6883         case 131:  /* log-buffer */
6884             if ( object_type == 25 )
6885                 offset = fEventLogRecord(tvb, pinfo, tree, offset);
6886             else if ( object_type == 27 )
6887                 offset = fLogMultipleRecord(tvb, pinfo, tree, offset);
6888             else
6889                 offset = fLogRecord(tvb, pinfo, tree, offset);
6890             break;
6891         case 159: /* member-of */
6892         case 165: /* zone-members */
6893             offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
6894             break;
6895         case 196: /* last-restart-reason */
6896             offset = fRestartReason(tvb, pinfo, tree, offset);
6897             break;
6898         case 212: /* actual-shed-level */
6899         case 214: /* expected-shed-level */
6900         case 218: /* requested-shed-level */
6901             offset = fShedLevel(tvb, pinfo, tree, offset);
6902             break;
6903         case 152: /* active-cov-subscriptions */
6904             offset = fCOVSubscription(tvb, pinfo, tree, offset);
6905             break;
6906         case 23: /* date-list */
6907             offset = fCalendarEntry(tvb, pinfo, tree, offset);
6908             break;
6909         case 116: /* time-sychronization-recipients */
6910             offset = fRecipient(tvb, pinfo, tree, offset);
6911             break;
6912         case 83: /* event-parameters */
6913             offset = fEventParameter(tvb, pinfo, tree, offset);
6914             break;
6915         case 211: /* subordinate-list */
6916             offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
6917             break;
6918         case 130: /* event-time-stamp */
6919             offset = fEventTimeStamps(tvb, pinfo, tree, offset);
6920             break;
6921         case 197: /* logging-type */
6922             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLoggingType);
6923             break;
6924         case 36: /* event-state */
6925             offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar, BACnetEventState, 64);
6926             break;
6927         case 103: /* reliability */
6928             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetReliability);
6929             break;
6930         case 72: /* notify-type */
6931             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNotifyType);
6932             break;
6933         case 208: /* node-type */
6934             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNodeType);
6935             break;
6936         case 231: /* door-status */
6937             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorStatus);
6938             break;
6939         case 233: /* lock-status */
6940             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLockStatus);
6941             break;
6942         case 235: /* secured-status */
6943             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorSecuredStatus);
6944             break;
6945         case 158: /* maintenance-required */
6946             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetMaintenance);
6947             break;
6948         case 92: /* program-state */
6949             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramState);
6950             break;
6951         case 90: /* program-change */
6952             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramRequest);
6953             break;
6954         case 100: /* reason-for-halt */
6955             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramError);
6956             break;
6957         case 160: /* mode */
6958             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyMode);
6959             break;
6960         case 163: /* silenced */
6961             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetSilencedState);
6962             break;
6963         case 161: /* operation-expected */
6964             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyOperation);
6965             break;
6966         case 164: /* tracking-value */
6967             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
6968             break;
6969         case 41: /* file-access-method */
6970             offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetFileAccessMethod);
6971             break;
6972         case 185:  /* prescale */
6973             offset = fPrescale(tvb, pinfo, tree, offset);
6974             break;
6975         case 187:  /* scale */
6976             offset = fScale(tvb, pinfo, tree, offset);
6977             break;
6978         case 184: /* logging-record */
6979             offset = fLoggingRecord(tvb, pinfo, tree, offset);
6980             break;
6981         case 228: /* door-members */
6982             offset = fDoorMembers(tvb, pinfo, tree, offset);
6983             break;
6984         case 181: /* input-reference */
6985             offset = fObjectPropertyReference(tvb, pinfo, tree, offset);
6986             break;
6987         case 78: /* object-property-reference */
6988             offset = fObjectPropertyReference(tvb, pinfo, tree, offset);
6989             break;
6990         case 234: /* masked-alarm-values */
6991             offset = fSequenceOfEnums(tvb, pinfo, tree, offset, "masked-alarm-value: ", BACnetDoorAlarmState);
6992             break;
6993         case 53:    /* list-of-group-members */
6994             save_object_type = object_type;
6995             offset = fListOfGroupMembers(tvb, pinfo, tree, offset);
6996             object_type = save_object_type;
6997             break;
6998         case 85:    /* present-value */
6999             if ( object_type == 11 )    /* group object handling of present-value */
7000             {
7001                 offset = fReadAccessResult(tvb, pinfo, tree, offset);
7002                 break;
7003             }
7004             /* intentially fall through here so don't reorder this case statement */
7005         default:
7006             if (tag_info) {
7007                 if (tag_is_opening(tag_info)) {
7008                     ++depth;
7009                     offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7010                 } else if (tag_is_closing(tag_info)) {
7011                     --depth;
7012                     offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7013                 } else {
7014                     offset  = fContextTaggedValue(tvb, pinfo, tree, offset, ar);
7015                 }
7016             } else {
7017                 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
7018             }
7019             break;
7020         }
7021         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7022     }
7023     return offset;
7024
7025 }
7026
7027 static guint
7028 fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_info)
7029 {
7030     guint8  tag_no;
7031     guint32 lvt;
7032
7033     if (tag_is_opening(tag_info)) {
7034         offset += fTagHeaderTree(tvb, pinfo, tree, offset,
7035                                  &tag_no, &tag_info, &lvt);
7036         offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
7037         if (tvb_reported_length_remaining(tvb, offset) > 0) {
7038             offset += fTagHeaderTree(tvb, pinfo, tree, offset,
7039                                      &tag_no, &tag_info, &lvt);
7040         }
7041     } else {
7042         proto_tree_add_text(tree, tvb, offset, tvb_reported_length(tvb) - offset,
7043                             "expected Opening Tag!");
7044         offset = tvb_reported_length(tvb);
7045     }
7046
7047     return offset;
7048 }
7049
7050
7051 static guint
7052 fPropertyIdentifierValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset)
7053 {
7054     guint   lastoffset = offset;
7055     guint8  tag_no, tag_info;
7056     guint32 lvt;
7057
7058     offset = fPropertyReference(tvb, pinfo, tree, offset, tagoffset, 0);
7059     if (offset > lastoffset) {
7060         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7061         if (tag_no == tagoffset+2) {  /* Value - might not be present in ReadAccessResult */
7062             offset = fPropertyValue(tvb, pinfo, tree, offset, tag_info);
7063         }
7064     }
7065     return offset;
7066 }
7067
7068 static guint
7069 fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7070 {
7071     guint   lastoffset = 0;
7072     guint8  tag_no, tag_info;
7073     guint32 lvt;
7074
7075     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7076         lastoffset = offset;
7077         offset = fPropertyIdentifierValue(tvb, pinfo, tree, offset, 0);
7078         if (offset > lastoffset) {
7079             /* detect optional priority
7080             by looking to see if the next tag is context tag number 3 */
7081             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7082             if (tag_is_context_specific(tag_info) && (tag_no == 3))
7083                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
7084         }
7085         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7086     }
7087     return offset;
7088 }
7089
7090 static guint
7091 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7092 {
7093     guint       lastoffset = 0, len;
7094     guint8      tag_no, tag_info;
7095     guint32     lvt;
7096     proto_tree *subtree = tree;
7097
7098     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7099         lastoffset = offset;
7100         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7101         if (tag_is_closing(tag_info)) {
7102             offset += len;
7103             subtree = tree;
7104             continue;
7105         }
7106
7107         switch (tag_no) {
7108         case 0: /* ProcessId */
7109             offset = fUnsignedTag(tvb, pinfo, tree, offset, "subscriber Process Id: ");
7110             break;
7111         case 1: /* monitored ObjectId */
7112             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7113             break;
7114         case 2: /* issueConfirmedNotifications */
7115             offset = fBooleanTag(tvb, pinfo, tree, offset, "issue Confirmed Notifications: ");
7116             break;
7117         case 3: /* life time */
7118             offset = fTimeSpan(tvb, pinfo, tree, offset, "life time");
7119             break;
7120         case 4: /* monitoredPropertyIdentifier */
7121             if (tag_is_opening(tag_info)) {
7122                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "monitoredPropertyIdentifier");
7123                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7124                 offset  = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
7125             } else {
7126                 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
7127             }
7128             break;
7129         case 5: /* covIncrement */
7130             offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
7131             break;
7132         default:
7133             return offset;
7134         }
7135         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7136     }
7137     return offset;
7138 }
7139
7140 static guint
7141 fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7142 {
7143     return fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
7144 }
7145
7146 static guint
7147 fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7148 {
7149     guint lastoffset = 0;
7150
7151     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7152         lastoffset = offset;
7153
7154         switch (fTagNo(tvb, offset)) {
7155         case 0: /* deviceInstanceLowLimit */
7156             offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance Low Limit: ");
7157             break;
7158         case 1: /* deviceInstanceHighLimit */
7159             offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance High Limit: ");
7160             break;
7161         case 2: /* BACnetObjectId */
7162             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7163             break;
7164         case 3: /* messageText */
7165             offset = fCharacterString(tvb, pinfo, tree, offset, "Object Name: ");
7166             break;
7167         default:
7168             return offset;
7169         }
7170         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7171     }
7172     return offset;
7173 }
7174
7175
7176 static guint
7177 fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
7178 {
7179     guint   lastoffset = 0;
7180     guint8  tag_no, tag_info;
7181     guint32 lvt;
7182
7183     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7184     if (tag_is_opening(tag_info) && tag_no == 0) {
7185         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* opening context tag 0 */
7186         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7187             lastoffset = offset;
7188             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7189             if (tag_is_closing(tag_info)) {
7190                 /* should be closing context tag 0 */
7191                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7192                 return offset;
7193             }
7194
7195             offset = fTimeValue(tvb, pinfo, subtree, offset);
7196             if (offset == lastoffset) break;    /* nothing happened, exit loop */
7197         }
7198     } else if ((tag_no == 0) && (lvt == 0)) {
7199         /* not sure null (empty array element) is legal */
7200         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7201     }
7202     return offset;
7203 }
7204
7205 static guint
7206 fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7207 {
7208     guint       lastoffset = 0;
7209     guint8      tag_no, tag_info;
7210     guint32     lvt;
7211     guint       i = 1; /* day of week array index */
7212     proto_tree *subtree = tree;
7213
7214     if (propertyArrayIndex > 0) {
7215         /* BACnetARRAY index 0 refers to the length
7216         of the array, not the elements of the array.
7217         BACnetARRAY index -1 is our internal flag that
7218         the optional index was not used.
7219         BACnetARRAY refers to this as all elements of the array.
7220         If the optional index is specified for a BACnetARRAY,
7221         then that specific array element is referenced. */
7222         i = propertyArrayIndex;
7223     }
7224     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7225         lastoffset = offset;
7226         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7227         if (tag_is_closing(tag_info)) {
7228             return offset; /* outer encoding will print out closing tag */
7229         }
7230         subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_bacapp_value, NULL,
7231                                 val_to_str(i++, day_of_week, "day of week (%d) not found"));
7232         offset = fDailySchedule(tvb, pinfo, subtree, offset);
7233         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7234     }
7235     return offset;
7236 }
7237
7238
7239 static guint
7240 fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7241 {
7242     if (tvb_reported_length_remaining(tvb, offset) <= 0)
7243         return offset;
7244
7245     return fDateTime(tvb, pinfo, tree, offset, "UTC-Time: ");
7246 }
7247
7248 static guint
7249 fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7250 {
7251     if (tvb_reported_length_remaining(tvb, offset) <= 0)
7252         return offset;
7253
7254     return fDateTime(tvb, pinfo, tree, offset, NULL);
7255 }
7256
7257 static guint
7258 fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7259 {
7260     if (tvb_reported_length_remaining(tvb, offset) <= 0)
7261         return offset;
7262     offset = fDate(tvb, pinfo, tree, offset, "Start Date: ");
7263     return fDate(tvb, pinfo, tree, offset, "End Date: ");
7264 }
7265
7266 static guint
7267 fVendorIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7268 {
7269     guint32      val   = 0;
7270     guint8       tag_no, tag_info;
7271     guint32      lvt;
7272     guint        tag_len;
7273     proto_item  *ti;
7274     proto_tree  *subtree;
7275     const gchar *label = "Vendor ID";
7276
7277     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7278     if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
7279         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7280             "%s: %s (%u)",
7281             label,
7282             val_to_str_ext_const(val, &BACnetVendorIdentifiers_ext, "Unknown Vendor"),
7283             val);
7284     else
7285         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7286             "%s - %u octets (Unsigned)", label, lvt);
7287     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7288     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7289
7290     if ((lvt < 1) || (lvt > 2)) { /* vendorIDs >= 1  and <= 2 are supported */
7291         proto_tree_add_expert_format(tree, pinfo, &ei_bacapp_bad_length, tvb, 0, lvt,
7292                                 "Wrong length indicated. Expected 1 or 2, got %u", lvt);
7293         return offset+tag_len+lvt;
7294     }
7295
7296     proto_tree_add_item(subtree, hf_BACnetVendorIdentifier, tvb,
7297         offset+tag_len, lvt, ENC_BIG_ENDIAN);
7298
7299     return offset+tag_len+lvt;
7300 }
7301
7302 static guint
7303 fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7304 {
7305     guint32      val   = 0;
7306     guint8       tag_no, tag_info;
7307     guint32      lvt;
7308     guint        tag_len;
7309     proto_item  *ti;
7310     proto_tree  *subtree;
7311     const gchar *label = "Restart Reason";
7312
7313     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7314     if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
7315         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7316             "%s: %s (%u)", label,
7317             val_to_str_const(val, BACnetRestartReason, "Unknown reason"), val);
7318     else
7319         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7320             "%s - %u octets (Unsigned)", label, lvt);
7321     subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7322     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7323
7324     if (lvt != 1) {
7325         proto_tree_add_expert_format(tree, pinfo, &ei_bacapp_bad_length, tvb, 0, lvt,
7326                                 "Wrong length indicated. Expected 1, got %u", lvt);
7327         return offset+tag_len+lvt;
7328     }
7329
7330     proto_tree_add_item(subtree, hf_BACnetRestartReason, tvb,
7331         offset+tag_len, lvt, ENC_BIG_ENDIAN);
7332
7333     return offset+tag_len+lvt;
7334 }
7335
7336 static guint
7337 fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7338 {
7339     guint lastoffset = 0;
7340
7341     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7342         lastoffset = offset;
7343         switch (fTagNo(tvb, offset)) {
7344
7345         case 0: /* textMessageSourceDevice */
7346             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7347             break;
7348         case 1: /* messageClass */
7349             switch (fTagNo(tvb, offset)) {
7350             case 0: /* numeric */
7351                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "message Class: ");
7352                 break;
7353             case 1: /* character */
7354                 offset = fCharacterString(tvb, pinfo, tree, offset, "message Class: ");
7355                 break;
7356             }
7357             break;
7358         case 2: /* messagePriority */
7359             offset = fEnumeratedTag(tvb, pinfo, tree, offset, "message Priority: ",
7360                 BACnetMessagePriority);
7361             break;
7362         case 3: /* message */
7363             offset = fCharacterString(tvb, pinfo, tree, offset, "message: ");
7364             break;
7365         default:
7366             return offset;
7367         }
7368         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7369     }
7370     return offset;
7371 }
7372
7373 static guint
7374 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7375 {
7376     return fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
7377 }
7378
7379 static guint
7380 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7381 {
7382     guint       lastoffset, len;
7383     guint8      tag_no, tag_info;
7384     guint32     lvt;
7385     proto_tree *subtree = tree;
7386     tvbuff_t   *next_tvb;
7387     guint       vendor_identifier = 0;
7388     guint       service_number = 0;
7389
7390     len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7391     fUnsigned32(tvb, offset+len, lvt, &vendor_identifier);
7392     if (col_get_writable(pinfo->cinfo))
7393         col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ", vendor_identifier);
7394     offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
7395
7396     next_tvb = tvb_new_subset_remaining(tvb, offset);
7397     if (dissector_try_uint(bacapp_dissector_table,
7398         vendor_identifier, next_tvb, pinfo, tree)) {
7399         /* we parsed it so skip over length and we are done */
7400         offset += tvb_reported_length(next_tvb);
7401         return offset;
7402     }
7403
7404     /* Not handled by vendor dissector */
7405
7406     /* exit loop if nothing happens inside */
7407     while (tvb_reported_length_remaining(tvb, offset) > 0) {
7408         lastoffset = offset;
7409         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7410         if (tag_is_closing(tag_info)) {
7411             if (tag_no == 2) { /* Make sure it's the expected tag */
7412                 offset += len;
7413                 subtree = tree;
7414                 continue;
7415             } else {
7416                 break; /* End loop if incorrect closing tag */
7417             }
7418         }
7419         switch (tag_no) {
7420
7421             /* vendorID is now parsed above */
7422         case 1: /* serviceNumber */
7423             fUnsigned32(tvb, offset+len, lvt, &service_number);
7424             if (col_get_writable(pinfo->cinfo))
7425                 col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ",   service_number);
7426             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
7427             break;
7428         case 2: /*serviceParameters */
7429             if (tag_is_opening(tag_info)) {
7430                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1,
7431                         ett_bacapp_value, NULL, "service Parameters");
7432                 propertyIdentifier = -1;
7433                 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
7434             } else {
7435                 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
7436             }
7437             break;
7438         default:
7439             return offset;
7440         }
7441         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7442     }
7443
7444     return offset;
7445 }
7446
7447 static guint
7448 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7449 {
7450     return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
7451 }
7452
7453 static guint
7454 fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7455 {
7456     return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
7457 }
7458
7459 static guint
7460 fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
7461 {
7462     guint       lastoffset = 0;
7463     guint8      tag_no, tag_info;
7464     guint32     lvt;
7465     proto_tree *subtree = tree;
7466
7467     if (label != NULL) {
7468         subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, label);
7469     }
7470
7471     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7472         lastoffset = offset;
7473         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7474
7475         switch (tag_no) {
7476         case 0: /* subscriberProcessId */
7477             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "requesting Process Id: ");
7478             break;
7479         case 1: /* requestingSource */
7480             offset = fCharacterString(tvb, pinfo, tree, offset, "requesting Source: ");
7481             break;
7482         case 2: /* request */
7483             offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
7484                 "request: ", BACnetLifeSafetyOperation, 64);
7485             break;
7486         case 3: /* objectId */
7487             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
7488             break;
7489         default:
7490             return offset;
7491         }
7492         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7493     }
7494     return offset;
7495 }
7496
7497 typedef struct _value_string_enum {
7498     const value_string *valstr;
7499 } value_string_enum;
7500
7501 static const value_string_enum
7502 BACnetPropertyStatesEnums[] = {
7503     { NULL },
7504     {BACnetBinaryPV },
7505     {BACnetEventType },
7506     {BACnetPolarity },
7507     {BACnetProgramRequest },
7508     {BACnetProgramState },
7509     {BACnetProgramError },
7510     {BACnetReliability },
7511     {BACnetEventState },
7512     {BACnetDeviceStatus },
7513     {BACnetEngineeringUnits },
7514     { NULL },
7515     {BACnetLifeSafetyMode },
7516     {BACnetLifeSafetyState },
7517     {BACnetRestartReason },
7518     {BACnetDoorAlarmState },
7519     {BACnetAction },
7520     {BACnetDoorSecuredStatus },
7521     {BACnetDoorStatus },
7522     { NULL }, /* {BACnetDoorValue }, */
7523     {BACnetFileAccessMethod },
7524     {BACnetLockStatus },
7525     {BACnetLifeSafetyOperation },
7526     {BACnetMaintenance },
7527     {BACnetNodeType },
7528     {BACnetNotifyType },
7529     { NULL }, /* {BACnetSecurityLevel }, */
7530     {BACnetShedState },
7531     {BACnetSilencedState },
7532     { NULL },
7533     { NULL }, /* {BACnetAccessEvent }, */
7534     { NULL }, /* {BACnetZoneOccupancyState }, */
7535     { NULL }, /* {BACnetAccessCredentialDisableReason }, */
7536     { NULL }, /* {BACnetAccessCredentialDisable }, */
7537     { NULL }, /* {BACnetAuthenticationStatus }, */
7538     { NULL },
7539     { NULL }, /* {BACnetBackupState }, */
7540 };
7541 #define BACnetPropertyStatesEnums_Size 36
7542
7543 static guint
7544 fBACnetPropertyStates(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
7545 {
7546     guint8       tag_no, tag_info;
7547     guint32      lvt;
7548     const gchar* label;
7549
7550     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7551     label = wmem_strdup_printf(wmem_packet_scope(), "%s: ",
7552                                val_to_str_const( tag_no, VALS(BACnetPropertyStates), "Unknown State" ));
7553
7554     switch (tag_no) {
7555     case 0:
7556         offset = fBooleanTag(tvb, pinfo, tree, offset, label);
7557         break;
7558     case 11:
7559         offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
7560         break;
7561     default:
7562         if ( (tag_no > BACnetPropertyStatesEnums_Size) ||
7563             VALS(BACnetPropertyStatesEnums[tag_no].valstr) == NULL)
7564         {
7565             offset = fEnumeratedTag(tvb, pinfo, tree, offset, label, NULL);
7566             /* don't use Abstract type here because it is context tagged and therefore we don't know app type */
7567         }
7568         else
7569         {
7570             offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label,
7571                     VALS(BACnetPropertyStatesEnums[tag_no].valstr), 64);
7572         }
7573         break;
7574     }
7575     return offset;
7576 }
7577
7578
7579 /*
7580 BACnetDeviceObjectPropertyValue ::= SEQUENCE {
7581       deviceIdentifier       [0]      BACnetObjectIdentifier,
7582       objectIdentifier       [1]      BACnetObjectIdentifier,
7583       propertyIdentifier     [2]      BACnetPropertyIdentifier,
7584       arrayIndex             [3]      Unsigned OPTIONAL,
7585       value                  [4]      ABSTRACT-SYNTAX.&Type
7586       }
7587 */
7588 static guint
7589 fDeviceObjectPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7590 {
7591     guint   lastoffset = 0;
7592     guint8  tag_no, tag_info;
7593     guint32 lvt;
7594
7595     while (tvb_reported_length_remaining(tvb, offset) > 0) {
7596         lastoffset = offset;
7597         /* check the tag.  A closing tag means we are done */
7598         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7599         if (tag_is_closing(tag_info)) {
7600             return offset;
7601         }
7602         switch (tag_no) {
7603         case 0: /* deviceIdentifier */
7604             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7605             break;
7606         case 1: /* objectIdentifier */
7607             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7608             break;
7609         case 2: /* propertyIdentifier */
7610             offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
7611             break;
7612         case 3: /* arrayIndex - OPTIONAL */
7613             offset = fUnsignedTag(tvb, pinfo, tree, offset,
7614                 "arrayIndex: ");
7615             break;
7616         case 4: /* value */
7617             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7618             offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
7619             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7620             break;
7621         default:
7622             return offset;
7623         }
7624         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7625     }
7626     return offset;
7627 }
7628
7629 /*
7630 BACnetDeviceObjectPropertyReference ::= SEQUENCE {
7631       objectIdentifier       [0]      BACnetObjectIdentifier,
7632       propertyIdentifier     [1]      BACnetPropertyIdentifier,
7633       propertyArrayIndex     [2]      Unsigned OPTIONAL, -- used only with array datatype
7634                                                                 -- if omitted with an array then
7635                                                                 -- the entire array is referenced
7636       deviceIdentifier       [3]      BACnetObjectIdentifier OPTIONAL
7637       }
7638 */
7639 static guint
7640 fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7641 {
7642     return fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
7643 }
7644
7645 /*
7646 BACnetDeviceObjectPropertyReference ::= SEQUENCE {
7647       objectIdentifier       [0]      BACnetObjectIdentifier,
7648       propertyIdentifier     [1]      BACnetPropertyIdentifier,
7649       propertyArrayIndex     [2]      Unsigned OPTIONAL, -- used only with array datatype
7650                                                                 -- if omitted with an array then
7651                                                                 -- the entire array is referenced
7652       deviceIdentifier       [3]      BACnetObjectIdentifier OPTIONAL
7653       }
7654 */
7655 static guint
7656 fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7657 {
7658     guint   lastoffset = 0;
7659     guint8  tag_no, tag_info;
7660     guint32 lvt;
7661
7662     while (tvb_reported_length_remaining(tvb, offset) > 0) {
7663         lastoffset = offset;
7664         /* check the tag.  A closing tag means we are done */
7665         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7666         if (tag_is_closing(tag_info)) {
7667             return offset;
7668         }
7669         switch (tag_no) {
7670         case 0: /* objectIdentifier */
7671             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7672             break;
7673         case 1: /* propertyIdentifier */
7674             offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
7675             break;
7676         case 2: /* arrayIndex - OPTIONAL */
7677             offset = fUnsignedTag(tvb, pinfo, tree, offset,
7678                 "arrayIndex: ");
7679             break;
7680         case 3: /* deviceIdentifier - OPTIONAL */
7681             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7682             break;
7683         default:
7684             return offset;
7685         }
7686         if (offset == lastoffset) break;     /* nothing happened, exit loop */
7687     }
7688     return offset;
7689 }
7690
7691 static guint
7692 fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7693 {
7694     guint       lastoffset = offset;
7695     guint8      tag_no, tag_info;
7696     guint32     lvt;
7697     proto_tree *subtree = tree;
7698
7699     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7700     subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
7701         ett_bacapp_value, NULL, "notification parameters (%d) %s",
7702         tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
7703     /* Opening tag for parameter choice */
7704     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7705
7706     switch (tag_no) {
7707     case 0: /* change-of-bitstring */
7708         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7709             lastoffset = offset;
7710             switch (fTagNo(tvb, offset)) {
7711             case 0:
7712                 offset = fBitStringTag(tvb, pinfo, subtree, offset,
7713                     "referenced-bitstring: ");
7714                 break;
7715             case 1:
7716                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7717                     "status-flags: ", BACnetStatusFlags);
7718                 lastoffset = offset;
7719                 break;
7720             default:
7721                 break;
7722             }
7723             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7724         }
7725         break;
7726     case 1: /* change-of-state */
7727         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7728             lastoffset = offset;
7729             switch (fTagNo(tvb, offset)) {
7730             case 0:
7731                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7732                 offset  = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
7733                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7734                 break;
7735             case 1:
7736                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7737                     "status-flags: ", BACnetStatusFlags);
7738                 lastoffset = offset;
7739                 break;
7740             default:
7741                 break;
7742             }
7743             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7744         }
7745         break;
7746     case 2: /* change-of-value */
7747         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7748             lastoffset = offset;
7749             switch (fTagNo(tvb, offset)) {
7750             case 0:
7751                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7752                 switch (fTagNo(tvb, offset)) {
7753                 case 0:
7754                     offset = fBitStringTag(tvb, pinfo, subtree, offset,
7755                         "changed-bits: ");
7756                     break;
7757                 case 1:
7758                     offset = fRealTag(tvb, pinfo, subtree, offset,
7759                         "changed-value: ");
7760                     break;
7761                 default:
7762                     break;
7763                 }
7764                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7765                 break;
7766             case 1:
7767                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7768                     "status-flags: ", BACnetStatusFlags);
7769                 lastoffset = offset;
7770                 break;
7771             default:
7772                 break;
7773             }
7774             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7775         }
7776         break;
7777     case 3: /* command-failure */
7778         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7779             lastoffset = offset;
7780             switch (fTagNo(tvb, offset)) {
7781             case 0: /* "command-value: " */
7782                 /* from BACnet Table 13-3,
7783                     Standard Object Property Values Returned in Notifications */
7784                 propertyIdentifier = 85; /* PRESENT_VALUE */
7785                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7786                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
7787                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7788                 break;
7789             case 1:
7790                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7791                     "status-flags: ", BACnetStatusFlags);
7792                 break;
7793             case 2: /* "feedback-value: " */
7794                 propertyIdentifier = 40; /* FEEDBACK_VALUE */
7795                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7796                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
7797                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7798                 lastoffset = offset;
7799                 break;
7800             default:
7801                 break;
7802             }
7803             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7804         }
7805         break;
7806     case 4: /* floating-limit */
7807         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7808             lastoffset = offset;
7809             switch (fTagNo(tvb, offset)) {
7810             case 0:
7811                 offset = fRealTag(tvb, pinfo, subtree, offset, "reference-value: ");
7812                 break;
7813             case 1:
7814                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7815                     "status-flags: ", BACnetStatusFlags);
7816                 break;
7817             case 2:
7818                 offset = fRealTag(tvb, pinfo, subtree, offset, "setpoint-value: ");
7819                 break;
7820             case 3:
7821                 offset = fRealTag(tvb, pinfo, subtree, offset, "error-limit: ");
7822                 lastoffset = offset;
7823                 break;
7824             default:
7825                 break;
7826             }
7827             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7828         }
7829         break;
7830     case 5: /* out-of-range */
7831         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7832             lastoffset = offset;
7833             switch (fTagNo(tvb, offset)) {
7834             case 0:
7835                 offset = fRealTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
7836                 break;
7837             case 1:
7838                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7839                     "status-flags: ", BACnetStatusFlags);
7840                 break;
7841             case 2:
7842                 offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
7843                 break;
7844             case 3:
7845                 offset = fRealTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
7846                 lastoffset = offset;
7847                 break;
7848             default:
7849                 break;
7850             }
7851             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7852         }
7853         break;
7854     case 6:
7855         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7856             lastoffset = offset;
7857             offset =fBACnetPropertyValue(tvb, pinfo, subtree, offset);
7858             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7859         }
7860         break;
7861     case 7: /* deprecated (was 'buffer-ready', changed and moved to [10]) */
7862         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7863             lastoffset = offset;
7864             switch (fTagNo(tvb, offset)) {
7865             case 0:
7866                 offset = fObjectIdentifier(tvb, pinfo, subtree, offset); /* buffer-device */
7867                 break;
7868             case 1:
7869                 offset = fObjectIdentifier(tvb, pinfo, subtree, offset); /* buffer-object */
7870                 break;
7871             case 2:
7872                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7873                 offset  = fDateTime(tvb, pinfo, subtree, offset, "previous-notification: ");
7874                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7875                 break;
7876             case 3:
7877                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7878                 offset  = fDateTime(tvb, pinfo, subtree, offset, "current-notification: ");
7879                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7880                 lastoffset = offset;
7881                 break;
7882             default:
7883                 break;
7884             }
7885             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7886         }
7887         break;
7888     case 8: /* change-of-life-safety */
7889         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7890             lastoffset = offset;
7891             switch (fTagNo(tvb, offset)) {
7892             case 0:
7893                 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
7894                     "new-state: ", BACnetLifeSafetyState, 256);
7895                 break;
7896             case 1:
7897                 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
7898                     "new-mode: ", BACnetLifeSafetyMode, 256);
7899                 break;
7900             case 2:
7901                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7902                     "status-flags: ", BACnetStatusFlags);
7903                 break;
7904             case 3:
7905                 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
7906                     "operation-expected: ", BACnetLifeSafetyOperation, 64);
7907                 lastoffset = offset;
7908                 break;
7909             default:
7910                 break;
7911             }
7912             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7913         }
7914         break;
7915     case 9: /* extended */
7916         while (tvb_reported_length_remaining(tvb, offset) > 0) {
7917             lastoffset = offset;
7918             switch (fTagNo(tvb, offset)) {
7919             case 0:
7920                 offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
7921                 break;
7922             case 1:
7923                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7924                     "extended-event-type: ");
7925                 break;
7926             case 2: /* parameters */
7927                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7928                 offset  = fApplicationTypes(tvb, pinfo, subtree, offset, "parameters: ");
7929                 offset  = fDeviceObjectPropertyValue(tvb, pinfo, subtree, offset);
7930                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7931                 lastoffset = offset;
7932                 break;
7933             default:
7934                 break;
7935             }
7936             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7937         }
7938         break;
7939     case 10: /* buffer ready */
7940         while (tvb_reported_length_remaining(tvb, offset) > 0) {
7941             lastoffset = offset;
7942             switch (fTagNo(tvb, offset)) {
7943             case 0: /* buffer-property */
7944                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7945                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
7946                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7947                 break;
7948             case 1:
7949                 offset  = fUnsignedTag(tvb, pinfo, subtree, offset,
7950                     "previous-notification: ");
7951                 break;
7952             case 2:
7953                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7954                     "current-notification: ");
7955                 lastoffset = offset;
7956                 break;
7957             default:
7958                 break;
7959             }
7960             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7961         }
7962         break;
7963     case 11: /* unsigned range */
7964         while (tvb_reported_length_remaining(tvb, offset) > 0) {
7965             lastoffset = offset;
7966             switch (fTagNo(tvb, offset)) {
7967             case 0:
7968                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7969                     "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,
7977                     "exceeded-limit: ");
7978                 lastoffset = offset;
7979                 break;
7980             default:
7981                 break;
7982             }
7983             if (offset == lastoffset) break;     /* nothing happened, exit loop */
7984         }
7985         break;
7986         /* 12 reserved */
7987     case 13: /* access-event */
7988         break;
7989     case 14: /* double-out-of-range */
7990         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7991             lastoffset = offset;
7992             switch (fTagNo(tvb, offset)) {
7993             case 0:
7994                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
7995                 break;
7996             case 1:
7997                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7998                     "status-flags: ", BACnetStatusFlags);
7999                 break;
8000             case 2:
8001                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
8002                 break;
8003             case 3:
8004                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
8005                 lastoffset = offset;
8006                 break;
8007             default:
8008                 break;
8009             }
8010             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8011         }
8012         break;
8013     case 15: /* signed-out-of-range */
8014         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8015             lastoffset = offset;
8016             switch (fTagNo(tvb, offset)) {
8017             case 0:
8018                 offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
8019                 break;
8020             case 1:
8021                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8022                     "status-flags: ", BACnetStatusFlags);
8023                 break;
8024             case 2:
8025                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8026                 break;
8027             case 3:
8028                 offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
8029                 lastoffset = offset;
8030                 break;
8031             default:
8032                 break;
8033             }
8034             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8035         }
8036         break;
8037     case 16: /* unsigned-out-of-range */
8038         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8039             lastoffset = offset;
8040             switch (fTagNo(tvb, offset)) {
8041             case 0:
8042                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
8043                 break;
8044             case 1:
8045                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8046                     "status-flags: ", BACnetStatusFlags);
8047                 break;
8048             case 2:
8049                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8050                 break;
8051             case 3:
8052                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
8053                 lastoffset = offset;
8054                 break;
8055             default:
8056                 break;
8057             }
8058             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8059         }
8060         break;
8061     case 17: /* change-of-characterstring */
8062         while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8063             lastoffset = offset;
8064             switch (fTagNo(tvb, offset)) {
8065             case 0:
8066                  /* changed-value (CharacterString) */
8067                 offset  = fCharacterString(tvb, pinfo, subtree, offset, "changed-value: ");
8068                 break;
8069             case 1:
8070                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8071                     "status-flags: ", BACnetStatusFlags);
8072                 break;
8073             case 2:
8074                 /* alarm-value (CharacterString) */
8075                 offset  = fCharacterString(tvb, pinfo, subtree, offset, "alarm-value: ");
8076                 lastoffset = offset;
8077                 break;
8078             default:
8079                 break;
8080             }
8081             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8082         }
8083         break;
8084     case 18: /* change-of-status-flags */
8085         while (tvb_reported_length_remaining(tvb, offset) > 0) {
8086             /* exit loop if nothing happens inside */
8087             lastoffset = offset;
8088             switch (fTagNo(tvb, offset)) {
8089             case 0:
8090                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8091                 offset = fApplicationTypesEnumerated(tvb, pinfo, subtree, offset,
8092                     "present-value: ", BACnetStatusFlags);
8093                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8094                 break;
8095             case 1:
8096                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8097                     "referenced-flags: ", BACnetStatusFlags);
8098                 lastoffset = offset;
8099                 break;
8100             default:
8101                 break;
8102             }
8103             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8104         }
8105         break;
8106         /* todo: add new parameters here ... */
8107     default:
8108         offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
8109         break;
8110     }
8111
8112     /* Closing tag for parameter choice */
8113     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8114
8115     return offset;
8116 }
8117
8118 static guint
8119 fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8120 {
8121     guint       lastoffset = offset;
8122     guint8      tag_no, tag_info;
8123     guint32     lvt;
8124     proto_tree *subtree = tree;
8125
8126     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8127     subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
8128         ett_bacapp_value, NULL, "event parameters (%d) %s",
8129         tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
8130
8131     /* Opening tag for parameter choice */
8132     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8133
8134     switch (tag_no) {
8135     case 0: /* change-of-bitstring */
8136         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8137             lastoffset = offset;
8138             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8139             if (tag_is_closing(tag_info)) {
8140                 break;
8141             }
8142             switch (tag_no) {
8143             case 0:
8144                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8145                 break;
8146             case 1:
8147                 offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
8148                 break;
8149             case 2: /* SEQUENCE OF BIT STRING */
8150                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8151                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8152                     lastoffset = offset;
8153                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8154                     if (tag_is_closing(tag_info)) {
8155                         break;
8156                     }
8157                     offset = fBitStringTag(tvb, pinfo, subtree, offset,
8158                                            "bitstring value: ");
8159                 }
8160                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8161                 break;
8162             default:
8163                 break;
8164             }
8165         }
8166         break;
8167     case 1: /* change-of-state */
8168         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8169             lastoffset = offset;
8170             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8171             if (tag_is_closing(tag_info)) {
8172                 break;
8173             }
8174             switch (tag_no) {
8175             case 0:
8176                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8177                 break;
8178             case 1: /* SEQUENCE OF BACnetPropertyStates */
8179                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8180                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8181                     lastoffset = offset;
8182                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8183                     if (tag_is_closing(tag_info)) {
8184                         break;
8185                     }
8186                     offset = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
8187                 }
8188                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8189                 break;
8190             default:
8191                 break;
8192             }
8193         }
8194         break;
8195     case 2: /* change-of-value */
8196         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8197             lastoffset = offset;
8198             switch (fTagNo(tvb, offset)) {
8199             case 0:
8200                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8201                 break;
8202             case 1: /* don't loop it, it's a CHOICE */
8203                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8204                 switch (fTagNo(tvb, offset)) {
8205                 case 0:
8206                     offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
8207                     break;
8208                 case 1:
8209                     offset = fRealTag(tvb, pinfo, subtree, offset,
8210                                        "referenced Property Increment: ");
8211                     break;
8212                 default:
8213                     break;
8214                 }
8215                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8216                 break;
8217             default:
8218                 break;
8219             }
8220         }
8221         break;
8222     case 3: /* command-failure */
8223         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8224             lastoffset = offset;
8225             tag_no = fTagNo(tvb, offset);
8226             switch (tag_no) {
8227             case 0:
8228                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8229                 break;
8230             case 1:
8231                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8232                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8233                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8234                 break;
8235             default:
8236                 break;
8237             }
8238         }
8239         break;
8240     case 4: /* floating-limit */
8241         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8242             lastoffset = offset;
8243             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8244             if (tag_is_closing(tag_info)) {
8245                 break;
8246             }
8247             switch (tag_no) {
8248             case 0:
8249                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8250                 break;
8251             case 1:
8252                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8253                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8254                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8255                 break;
8256             case 2:
8257                 offset  = fRealTag(tvb, pinfo, subtree, offset, "low diff limit: ");
8258                 break;
8259             case 3:
8260                 offset  = fRealTag(tvb, pinfo, subtree, offset, "high diff limit: ");
8261                 break;
8262             case 4:
8263                 offset  = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
8264                 break;
8265             default:
8266                 break;
8267             }
8268         }
8269         break;
8270     case 5: /* out-of-range */
8271         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8272             lastoffset = offset;
8273             switch (fTagNo(tvb, offset)) {
8274             case 0:
8275                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8276                 break;
8277             case 1:
8278                 offset = fRealTag(tvb, pinfo, subtree, offset, "low limit: ");
8279                 break;
8280             case 2:
8281                 offset = fRealTag(tvb, pinfo, subtree, offset, "high limit: ");
8282                 break;
8283             case 3:
8284                 offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
8285                 break;
8286             default:
8287                 break;
8288             }
8289         }
8290         break;
8291         /*  deprectated
8292             case 6:
8293             offset = fBACnetPropertyValue (tvb, pinfo, tree, offset);
8294             break;
8295         */
8296
8297     case 7: /* buffer-ready */
8298 #if 0
8299         /* deprecated */
8300         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
8301             lastoffset = offset;
8302             switch (fTagNo(tvb, offset)) {
8303             case 0:
8304                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "notification threshold");
8305                 break;
8306             case 1:
8307                 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8308                                        "previous notification count: ");
8309                 break;
8310             default:
8311                 return offset;
8312             }
8313         }
8314 #endif
8315         break;
8316     case 8: /* change-of-life-safety */
8317         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8318             lastoffset = offset;
8319             switch (fTagNo(tvb, offset)) {
8320             case 0:
8321                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8322                 break;
8323             case 1:
8324                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8325                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8326                     lastoffset = offset;
8327                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8328                     if (tag_is_closing(tag_info)) {
8329                         break;
8330                     }
8331                     offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
8332                                                   "life safety alarm value: ", BACnetLifeSafetyState, 256);
8333                 }
8334                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8335                 break;
8336             case 2:
8337                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8338                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8339                     lastoffset = offset;
8340                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8341                     if (tag_is_closing(tag_info)) {
8342                         break;
8343                     }
8344                     offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
8345                                                   "alarm value: ", BACnetLifeSafetyState, 256);
8346                 }
8347                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8348                 break;
8349             case 3:
8350                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8351                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8352                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8353                 break;
8354             default:
8355                 break;
8356             }
8357         }
8358         break;
8359     case 9: /* extended */
8360         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8361             lastoffset = offset;
8362             switch (fTagNo(tvb, offset)) {
8363             case 0:
8364                 offset = fVendorIdentifier(tvb, pinfo, tree, offset);
8365                 break;
8366             case 1:
8367                 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8368                                        "extended-event-type: ");
8369                 break;
8370             case 2: /* parameters */
8371                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8372                 offset  = fApplicationTypes(tvb, pinfo, tree, offset, "parameters: ");
8373                 offset  = fDeviceObjectPropertyValue(tvb, pinfo, tree, offset);
8374                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8375                 lastoffset = offset;
8376                 break;
8377             default:
8378                 break;
8379             }
8380             if (offset == lastoffset) break;     /* nothing happened, exit loop */
8381         }
8382         break;
8383     case 10: /* buffer-ready */
8384         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8385             lastoffset = offset;
8386             switch (fTagNo(tvb, offset)) {
8387             case 0:
8388                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
8389                                        "notification-threshold: ");
8390                 break;
8391             case 1:
8392                 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
8393                                        "previous-notification-count: ");
8394                 break;
8395             default:
8396                 break;
8397             }
8398         }
8399         break;
8400     case 11: /* unsigned-range */
8401         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8402             lastoffset = offset;
8403             switch (fTagNo(tvb, offset)) {
8404             case 0:
8405                 offset = fTimeSpan(tvb, pinfo, tree, offset, "Time Delay");
8406                 break;
8407             case 1:
8408                 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8409                                        "low-limit: ");
8410                 break;
8411             case 2:
8412                 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8413                                        "high-limit: ");
8414                 break;
8415             default:
8416                 break;
8417             }
8418         }
8419         break;
8420     case 13: /* access-event */
8421         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8422             lastoffset = offset;
8423             switch (fTagNo(tvb, offset)) {
8424             case 0:
8425                 /* TODO: [0] SEQUENCE OF BACnetAccessEvent */
8426                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8427                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8428                     lastoffset = offset;
8429                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8430                     if (tag_is_closing(tag_info)) {
8431                         break;
8432                     }
8433                     offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
8434                                                   "access event: ", BACnetAccessEvent, 512);
8435                 }
8436                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8437                 break;
8438             case 1:
8439                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8440                 offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8441                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8442                 break;
8443             default:
8444                 break;
8445             }
8446         }
8447         break;
8448     case 14: /* double-out-of-range */
8449         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8450             lastoffset = offset;
8451             switch (fTagNo(tvb, offset)) {
8452             case 0:
8453                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8454                 break;
8455             case 1:
8456                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "low limit: ");
8457                 break;
8458             case 2:
8459                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "high limit: ");
8460                 break;
8461             case 3:
8462                 offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
8463                 break;
8464             default:
8465                 break;
8466             }
8467         }
8468         break;
8469     case 15: /* signed-out-of-range */
8470         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8471             lastoffset = offset;
8472             switch (fTagNo(tvb, offset)) {
8473             case 0:
8474                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8475                 break;
8476             case 1:
8477                 offset = fSignedTag(tvb, pinfo, subtree, offset, "low limit: ");
8478                 break;
8479             case 2:
8480                 offset = fSignedTag(tvb, pinfo, subtree, offset, "high limit: ");
8481                 break;
8482             case 3:
8483                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8484                 break;
8485             default:
8486                 break;
8487             }
8488         }
8489         break;
8490     case 16: /* unsigned-out-of-range */
8491         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8492             lastoffset = offset;
8493             switch (fTagNo(tvb, offset)) {
8494             case 0:
8495                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8496                 break;
8497             case 1:
8498                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "low limit: ");
8499                 break;
8500             case 2:
8501                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "high limit: ");
8502                 break;
8503             case 3:
8504                 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8505                 break;
8506             default:
8507                 break;
8508             }
8509         }
8510         break;
8511     case 17: /* change-of-characterstring */
8512         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8513             lastoffset = offset;
8514             switch (fTagNo(tvb, offset)) {
8515             case 0:
8516                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8517                 break;
8518             case 1: /* SEQUENCE OF CharacterString */
8519                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8520                 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8521                     lastoffset = offset;
8522                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8523                     if (tag_is_closing(tag_info)) {
8524                         break;
8525                     }
8526                     offset  = fCharacterString(tvb, pinfo, tree, offset, "alarm value: ");
8527                 }
8528                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8529                 break;
8530             default:
8531                 break;
8532             }
8533         }
8534         break;
8535     case 18: /* change-of-status-flags */
8536         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
8537             lastoffset = offset;
8538             switch (fTagNo(tvb, offset)) {
8539             case 0:
8540                 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8541                 break;
8542             case 1:
8543                 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8544                     "selected flags: ", BACnetStatusFlags);
8545                 break;
8546             default:
8547                 break;
8548             }
8549         }
8550         break;
8551         /* todo: add new event-parameter cases here */
8552     default:
8553         break;
8554     }
8555
8556     /* Closing tag for parameter choice */
8557     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8558     return offset;
8559 }
8560
8561 static guint
8562 fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8563 {
8564     guint       lastoffset = 0;
8565     guint8      tag_no, tag_info;
8566     guint32     lvt;
8567     proto_tree *subtree = tree;
8568
8569     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8570         lastoffset = offset;
8571         switch (fTagNo(tvb, offset)) {
8572         case 0: /* timestamp */
8573             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8574             offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
8575             offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
8576             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8577             break;
8578         case 1: /* logDatum: don't loop, it's a CHOICE */
8579             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8580             switch (fTagNo(tvb, offset)) {
8581             case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
8582                 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
8583                 break;
8584             case 1: /* todo: move this to new method fConfirmedEventNotificationRequestTag... */
8585                 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "notification: ");
8586                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8587                 offset  = fConfirmedEventNotificationRequest(tvb, pinfo, subtree, offset);
8588                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8589                 break;
8590             case 2:
8591                 offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
8592                 break;
8593             default:
8594                 return offset;
8595             }
8596             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8597             break;
8598         default:
8599             return offset;
8600         }
8601         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8602     }
8603     return offset;
8604 }
8605
8606 static guint
8607 fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8608 {
8609     guint   lastoffset = 0;
8610     guint8  tag_no, tag_info;
8611     guint32 lvt;
8612
8613     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8614         lastoffset = offset;
8615         switch (fTagNo(tvb, offset)) {
8616         case 0: /* timestamp */
8617             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8618             offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
8619             offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
8620             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8621             break;
8622         case 1: /* logDatum: don't loop, it's a CHOICE */
8623             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8624             switch (fTagNo(tvb, offset)) {
8625             case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
8626                 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
8627                 break;
8628             case 1:
8629                 offset = fBooleanTag(tvb, pinfo, tree, offset, "boolean-value: ");
8630                 break;
8631             case 2:
8632                 offset = fRealTag(tvb, pinfo, tree, offset, "real value: ");
8633                 break;
8634             case 3:
8635                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "enum value: ");
8636                 break;
8637             case 4:
8638                 offset = fUnsignedTag(tvb, pinfo, tree, offset, "unsigned value: ");
8639                 break;
8640             case 5:
8641                 offset = fSignedTag(tvb, pinfo, tree, offset, "signed value: ");
8642                 break;
8643             case 6:
8644                 offset = fBitStringTag(tvb, pinfo, tree, offset, "bitstring value: ");
8645                 break;
8646             case 7:
8647                 offset = fNullTag(tvb, pinfo, tree, offset, "null value: ");
8648                 break;
8649             case 8:
8650                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8651                 offset  = fError(tvb, pinfo, tree, offset);
8652                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8653                 break;
8654             case 9:
8655                 offset = fRealTag(tvb, pinfo, tree, offset, "time change: ");
8656                 break;
8657             case 10:    /* any Value */
8658                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8659                 offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
8660                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8661                 break;
8662             default:
8663                 return offset;
8664             }
8665             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8666             break;
8667         case 2:
8668             /* Changed this to BitString per BACnet Spec. */
8669             offset = fBitStringTagVS(tvb, pinfo, tree, offset, "Status Flags:", BACnetStatusFlags);
8670             break;
8671         default:
8672             return offset;
8673         }
8674         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8675     }
8676     return offset;
8677 }
8678
8679 static guint
8680 fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8681 {
8682     guint   lastoffset = 0;
8683     guint8  tag_no, tag_info;
8684     guint32 lvt;
8685
8686     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8687         lastoffset = offset;
8688         switch (fTagNo(tvb, offset)) {
8689         case 0: /* timestamp */
8690             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8691             offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
8692             offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
8693             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8694             break;
8695         case 1: /* logData: don't loop, it's a CHOICE */
8696             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8697             switch (fTagNo(tvb, offset)) {
8698             case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
8699                 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
8700                 break;
8701             case 1: /* log-data: SEQUENCE OF CHOICE */
8702                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8703                 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset != lastoffset)) {  /* exit loop if nothing happens inside */
8704                     lastoffset = offset;
8705                     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8706                     if (tag_is_closing(tag_info)) {
8707                         lastoffset = offset;
8708                         break;
8709                     }
8710                     switch (tag_no) {
8711                     case 0:
8712                         offset = fBooleanTag(tvb, pinfo, tree, offset, "boolean-value: ");
8713                         break;
8714                     case 1:
8715                         offset = fRealTag(tvb, pinfo, tree, offset, "real value: ");
8716                         break;
8717                     case 2:
8718                         offset = fUnsignedTag(tvb, pinfo, tree, offset, "enum value: ");
8719                         break;
8720                     case 3:
8721                         offset = fUnsignedTag(tvb, pinfo, tree, offset, "unsigned value: ");
8722                         break;
8723                     case 4:
8724                         offset = fSignedTag(tvb, pinfo, tree, offset, "signed value: ");
8725                         break;
8726                     case 5:
8727                         offset = fBitStringTag(tvb, pinfo, tree, offset, "bitstring value: ");
8728                         break;
8729                     case 6:
8730                         offset = fNullTag(tvb, pinfo, tree, offset, "null value: ");
8731                         break;
8732                     case 7:
8733                         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8734                         offset  = fError(tvb, pinfo, tree, offset);
8735                         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8736                         break;
8737                     case 8: /* any Value */
8738                         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8739                         offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
8740                         offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8741                         break;
8742                     default:
8743                         return offset;
8744                     }
8745                 }
8746                 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8747                 break;
8748             case 2:
8749                 offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
8750                 break;
8751             default:
8752                 return offset;
8753             }
8754             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8755             break;
8756         default:
8757             return offset;
8758         }
8759         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8760     }
8761     return offset;
8762 }
8763
8764
8765 static guint
8766 fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8767 {
8768     guint   lastoffset = 0;
8769     guint8  tag_no, tag_info;
8770     guint32 lvt;
8771
8772     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8773         lastoffset = offset;
8774         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8775         if (tag_is_closing(tag_info)) {
8776             break;
8777         }
8778
8779         switch (tag_no) {
8780         case 0: /* ProcessId */
8781             offset  = fProcessId(tvb, pinfo, tree, offset);
8782             break;
8783         case 1: /* initiating ObjectId */
8784             offset  = fObjectIdentifier(tvb, pinfo, tree, offset);
8785             break;
8786         case 2: /* event ObjectId */
8787             offset  = fObjectIdentifier(tvb, pinfo, tree, offset);
8788             break;
8789         case 3: /* time stamp */
8790             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8791             offset  = fTimeStamp(tvb, pinfo, tree, offset, NULL);
8792             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8793             break;
8794         case 4: /* notificationClass */
8795             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
8796             break;
8797         case 5: /* Priority */
8798             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
8799             break;
8800         case 6: /* EventType */
8801             offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8802                 "Event Type: ", BACnetEventType, 64);
8803             break;
8804         case 7: /* messageText */
8805             offset  = fCharacterString(tvb, pinfo, tree, offset, "message Text: ");
8806             break;
8807         case 8: /* NotifyType */
8808             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
8809                 "Notify Type: ", BACnetNotifyType);
8810             break;
8811         case 9: /* ackRequired */
8812             offset  = fBooleanTag(tvb, pinfo, tree, offset, "ack Required: ");
8813             break;
8814         case 10: /* fromState */
8815             offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8816                 "from State: ", BACnetEventState, 64);
8817             break;
8818         case 11: /* toState */
8819             offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8820                 "to State: ", BACnetEventState, 64);
8821             break;
8822         case 12: /* NotificationParameters */
8823             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8824             offset  = fNotificationParameters(tvb, pinfo, tree, offset);
8825             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8826             break;
8827         default:
8828             break;
8829         }
8830         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8831     }
8832     return offset;
8833 }
8834
8835 static guint
8836 fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8837 {
8838     return fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
8839 }
8840
8841 static guint
8842 fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8843 {
8844     guint       lastoffset = 0, len;
8845     guint8      tag_no, tag_info;
8846     guint32     lvt;
8847     proto_tree *subtree    = tree;
8848
8849     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8850         lastoffset = offset;
8851         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8852         if (tag_is_closing(tag_info)) {
8853             offset += len;
8854             subtree = tree;
8855             continue;
8856         }
8857
8858         switch (tag_no) {
8859         case 0: /* ProcessId */
8860             offset = fProcessId(tvb, pinfo, tree, offset);
8861             break;
8862         case 1: /* initiating DeviceId */
8863             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
8864             break;
8865         case 2: /* monitored ObjectId */
8866             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
8867             break;
8868         case 3: /* time remaining */
8869             offset = fTimeSpan(tvb, pinfo, tree, offset, "Time remaining");
8870             break;
8871         case 4: /* List of Values */
8872             if (tag_is_opening(tag_info)) {
8873                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list of Values");
8874                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8875                 offset  = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
8876             } else {
8877                 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
8878             }
8879             break;
8880         default:
8881             return offset;
8882         }
8883         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8884     }
8885     return offset;
8886 }
8887
8888 static guint
8889 fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8890 {
8891     return fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
8892 }
8893
8894 static guint
8895 fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8896 {
8897     guint   lastoffset = 0;
8898     guint8  tag_no = 0, tag_info = 0;
8899     guint32 lvt = 0;
8900
8901     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8902         lastoffset = offset;
8903         switch (fTagNo(tvb, offset)) {
8904         case 0: /* acknowledgingProcessId */
8905             offset = fUnsignedTag(tvb, pinfo, tree, offset, "acknowledging Process Id: ");
8906             break;
8907         case 1: /* eventObjectId */
8908             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
8909             break;
8910         case 2: /* eventStateAcknowledged */
8911             offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8912                 "event State Acknowledged: ", BACnetEventState, 64);
8913             break;
8914         case 3: /* timeStamp */
8915             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8916             offset  = fTimeStamp(tvb, pinfo, tree, offset, NULL);
8917             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8918             break;
8919         case 4: /* acknowledgementSource */
8920             offset  = fCharacterString(tvb, pinfo, tree, offset, "acknowledgement Source: ");
8921             break;
8922         case 5: /* timeOfAcknowledgement */
8923             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8924             offset  = fTimeStamp(tvb, pinfo, tree, offset, "acknowledgement timestamp: ");
8925             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8926             break;
8927         default:
8928             return offset;
8929         }
8930         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8931     }
8932     return offset;
8933 }
8934
8935 static guint
8936 fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8937 {
8938     guint lastoffset = 0;
8939
8940     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8941         lastoffset = offset;
8942         offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
8943         offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
8944             "alarm State: ", BACnetEventState, 64);
8945         offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
8946             "acknowledged Transitions: ", BACnetEventTransitionBits);
8947         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8948     }
8949     return  offset;
8950 }
8951
8952 static guint
8953 fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8954 {
8955     guint   lastoffset = 0;
8956     guint8  tag_no, tag_info;
8957     guint32 lvt;
8958
8959     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8960         lastoffset = offset;
8961         switch (fTagNo(tvb, offset)) {
8962         case 0: /* acknowledgmentFilter */
8963             offset = fEnumeratedTag(tvb, pinfo, tree, offset,
8964                 "acknowledgment Filter: ", BACnetAcknowledgementFilter);
8965             break;
8966         case 1: /* eventObjectId - OPTIONAL */
8967             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8968             offset  = fRecipientProcess(tvb, pinfo, tree, offset);
8969             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8970             break;
8971         case 2: /* eventStateFilter */
8972             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
8973                 "event State Filter: ", BACnetEventStateFilter);
8974             break;
8975         case 3: /* eventTypeFilter - OPTIONAL */
8976             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
8977                 "event Type Filter: ", BACnetEventType);
8978             break;
8979         case 4: /* priorityFilter */
8980             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8981             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "min Priority: ");
8982             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "max Priority: ");
8983             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8984             break;
8985         case 5: /* notificationClassFilter - OPTIONAL */
8986             offset  = fUnsignedTag(tvb, pinfo, tree, offset, "notification Class Filter: ");
8987             break;
8988         default:
8989             return offset;
8990         }
8991         if (offset == lastoffset) break;     /* nothing happened, exit loop */
8992     }
8993     return offset;
8994 }
8995
8996 static guint
8997 fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8998 {
8999     guint lastoffset = 0;
9000
9001     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9002         lastoffset = offset;
9003         offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
9004         offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
9005             "event Type: ", BACnetEventType, 64);
9006         offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
9007             "event State: ", BACnetEventState);
9008         offset = fApplicationTypes(tvb, pinfo, tree, offset, "Priority: ");
9009         if (tvb_reported_length_remaining(tvb, offset) > 0 && fTagNo(tvb, offset) == 2)  /* Notification Class - OPTIONAL */
9010             offset = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
9011         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9012     }
9013
9014     return  offset;
9015 }
9016
9017 static guint
9018 fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9019 {
9020     if (tvb_reported_length_remaining(tvb, offset) > 0) {
9021         if (fTagNo(tvb, offset) == 0) {
9022             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9023         }
9024     }
9025     return offset;
9026 }
9027
9028 static guint
9029 flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9030 {
9031     guint       lastoffset = 0;
9032     guint8      tag_no, tag_info;
9033     guint32     lvt;
9034     proto_tree* subtree = tree;
9035
9036     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9037         lastoffset = offset;
9038         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9039         /* we are finished here if we spot a closing tag */
9040         if (tag_is_closing(tag_info)) {
9041             break;
9042         }
9043         switch (tag_no) {
9044         case 0: /* ObjectId */
9045             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9046             break;
9047         case 1: /* eventState */
9048             offset = fEnumeratedTag(tvb, pinfo, tree, offset,
9049                 "event State: ", BACnetEventState);
9050             break;
9051         case 2: /* acknowledgedTransitions */
9052             offset = fBitStringTagVS(tvb, pinfo, tree, offset,
9053                 "acknowledged Transitions: ", BACnetEventTransitionBits);
9054             break;
9055         case 3: /* eventTimeStamps */
9056             subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventTimeStamps");
9057             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9058             offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
9059             offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
9060             offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
9061             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9062             break;
9063         case 4: /* notifyType */
9064             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
9065                 "Notify Type: ", BACnetNotifyType);
9066             break;
9067         case 5: /* eventEnable */
9068             offset  = fBitStringTagVS(tvb, pinfo, tree, offset,
9069                 "event Enable: ", BACnetEventTransitionBits);
9070             break;
9071         case 6: /* eventPriorities */
9072             subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventPriorities");
9073             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9074             offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-OFFNORMAL Priority: ");
9075             offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-FAULT Priority: ");
9076             offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-NORMAL Priority: ");
9077             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9078             break;
9079         default:
9080             return offset;
9081         }
9082         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9083     }
9084     return offset;
9085 }
9086
9087 static guint
9088 fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9089 {
9090     guint   lastoffset = 0;
9091     guint8  tag_no, tag_info;
9092     guint32 lvt;
9093
9094     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9095     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9096         lastoffset = offset;
9097         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9098         /* we are finished here if we spot a closing tag */
9099         if (tag_is_closing(tag_info)) {
9100             break;
9101         }
9102         offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
9103         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9104     }
9105     return offset;
9106 }
9107
9108 static guint
9109 fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9110 {
9111     guint   lastoffset = 0;
9112     guint8  tag_no, tag_info;
9113     guint32 lvt;
9114
9115     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9116         lastoffset = offset;
9117         switch (fTagNo(tvb, offset)) {
9118         case 0: /* listOfEventSummaries */
9119             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9120             offset  = flistOfEventSummaries(tvb, pinfo, tree, offset);
9121             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9122             break;
9123         case 1: /* moreEvents */
9124             offset  = fBooleanTag(tvb, pinfo, tree, offset, "more Events: ");
9125             break;
9126         default:
9127             return offset;
9128         }
9129         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9130     }
9131     return offset;
9132 }
9133
9134 static guint
9135 fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9136 {
9137     guint       lastoffset = 0, len;
9138     guint8      tag_no, tag_info;
9139     guint32     lvt;
9140     proto_tree *subtree    = tree;
9141
9142     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9143
9144     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9145         lastoffset = offset;
9146         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9147         if (tag_is_closing(tag_info)) {
9148             offset += len;
9149             subtree = tree;
9150             continue;
9151         }
9152
9153         switch (tag_no) {
9154         case 0: /* ObjectId */
9155             offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
9156             break;
9157         case 3: /* listOfElements */
9158             if (tag_is_opening(tag_info)) {
9159                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfElements");
9160                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9161                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
9162             } else {
9163                 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
9164             }
9165             break;
9166         default:
9167             return offset;
9168         }
9169         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9170     }
9171     return offset;
9172 }
9173
9174 static guint
9175 fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9176 {
9177     return fObjectIdentifier(tvb, pinfo, tree, offset);
9178 }
9179
9180 static guint
9181 fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9182 {
9183     guint lastoffset = 0;
9184
9185     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9186         lastoffset = offset;
9187
9188         switch (fTagNo(tvb, offset)) {
9189         case 0: /* timeDuration */
9190             offset = fUnsignedTag(tvb, pinfo, tree, offset, "time Duration: ");
9191             break;
9192         case 1: /* enable-disable */
9193             offset = fEnumeratedTag(tvb, pinfo, tree, offset, "enable-disable: ",
9194                 BACnetEnableDisable);
9195             break;
9196         case 2: /* password - OPTIONAL */
9197             offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
9198             break;
9199         default:
9200             return offset;
9201         }
9202         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9203     }
9204     return offset;
9205 }
9206
9207 static guint
9208 fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9209 {
9210     guint lastoffset = 0;
9211
9212     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9213         lastoffset = offset;
9214
9215         switch (fTagNo(tvb, offset)) {
9216         case 0: /* reinitializedStateOfDevice */
9217             offset = fEnumeratedTag(tvb, pinfo, tree, offset,
9218                 "reinitialized State Of Device: ",
9219                 BACnetReinitializedStateOfDevice);
9220             break;
9221         case 1: /* password - OPTIONAL */
9222             offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
9223             break;
9224         default:
9225             return offset;
9226         }
9227         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9228     }
9229     return offset;
9230 }
9231
9232 static guint
9233 fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9234 {
9235     offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
9236                                           "vtClass: ", BACnetVTClass);
9237     return fApplicationTypes(tvb, pinfo, tree, offset, "local VT Session ID: ");
9238 }
9239
9240 static guint
9241 fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9242 {
9243     return fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
9244 }
9245
9246 static guint
9247 fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9248 {
9249     guint lastoffset = 0;
9250
9251     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9252         lastoffset = offset;
9253         offset= fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
9254         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9255     }
9256     return offset;
9257 }
9258
9259 static guint
9260 fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9261 {
9262     offset= fApplicationTypes(tvb, pinfo, tree, offset, "VT Session ID: ");
9263     offset = fApplicationTypes(tvb, pinfo, tree, offset, "VT New Data: ");
9264     return fApplicationTypes(tvb, pinfo, tree, offset, "VT Data Flag: ");
9265 }
9266
9267 static guint
9268 fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9269 {
9270     guint lastoffset = 0;
9271
9272     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9273         lastoffset = offset;
9274
9275         switch (fTagNo(tvb, offset)) {
9276         case 0: /* BOOLEAN */
9277             offset = fBooleanTag(tvb, pinfo, tree, offset, "all New Data Accepted: ");
9278             break;
9279         case 1: /* Unsigned OPTIONAL */
9280             offset = fUnsignedTag(tvb, pinfo, tree, offset, "accepted Octet Count: ");
9281             break;
9282         default:
9283             return offset;
9284         }
9285         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9286     }
9287     return offset;
9288 }
9289
9290 static guint
9291 fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9292 {
9293     guint lastoffset = 0;
9294
9295     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9296         lastoffset = offset;
9297
9298         switch (fTagNo(tvb, offset)) {
9299         case 0: /* Unsigned32 */
9300             offset = fUnsignedTag(tvb, pinfo, tree, offset, "pseudo Random Number: ");
9301             break;
9302         case 1: /* expected Invoke ID Unsigned8 OPTIONAL */
9303             proto_tree_add_item(tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
9304             break;
9305         case 2: /* Chararacter String OPTIONAL */
9306             offset = fCharacterString(tvb, pinfo, tree, offset, "operator Name: ");
9307             break;
9308         case 3: /* Chararacter String OPTIONAL */
9309             offset = fCharacterString(tvb, pinfo, tree, offset, "operator Password: ");
9310             break;
9311         case 4: /* Boolean OPTIONAL */
9312             offset = fBooleanTag(tvb, pinfo, tree, offset, "start Encyphered Session: ");
9313             break;
9314         default:
9315             return offset;
9316         }
9317         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9318     }
9319     return offset;
9320 }
9321
9322 static guint
9323 fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9324 {
9325     return fApplicationTypes(tvb, pinfo, tree, offset, "modified Random Number: ");
9326 }
9327
9328 static guint
9329 fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9330 {
9331     offset = fObjectIdentifier(tvb, pinfo, tree, offset); /* Requesting Device Identifier */
9332     offset = fAddress(tvb, pinfo, tree, offset);
9333     offset = fObjectIdentifier(tvb, pinfo, tree, offset); /* Remote Device Identifier */
9334     return fAddress(tvb, pinfo, tree, offset);
9335 }
9336
9337 static guint
9338 fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9339 {
9340     /* Same as AddListElement request after service choice */
9341     return fAddListElementRequest(tvb, pinfo, tree, offset);
9342 }
9343
9344 static guint
9345 fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9346 {
9347     return fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
9348 }
9349
9350 static guint
9351 fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9352 {
9353     guint       lastoffset = 0, len;
9354     guint8      tag_no, tag_info;
9355     guint32     lvt;
9356     proto_tree *subtree = tree;
9357
9358     /* set the optional global properties to indicate not-used */
9359     propertyArrayIndex = -1;
9360     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9361         lastoffset = offset;
9362         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9363         if (tag_is_closing(tag_info)) {
9364             offset += len;
9365             subtree = tree;
9366             continue;
9367         }
9368         switch (tag_no) {
9369         case 0: /* objectIdentifier */
9370             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9371             break;
9372         case 1: /* propertyIdentifier */
9373             offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
9374             break;
9375         case 2: /* propertyArrayIndex */
9376             offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
9377             break;
9378         case 3: /* propertyValue */
9379             offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
9380             break;
9381         default:
9382             break;
9383         }
9384         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9385     }
9386     return offset;
9387 }
9388
9389 static guint
9390 fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9391 {
9392     guint       lastoffset = 0;
9393     guint8      tag_no, tag_info;
9394     guint32     lvt;
9395     proto_tree *subtree = tree;
9396
9397     /* set the optional global properties to indicate not-used */
9398     propertyArrayIndex = -1;
9399     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9400         lastoffset = offset;
9401         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9402         /* quit loop if we spot a closing tag */
9403         if (tag_is_closing(tag_info)) {
9404             break;
9405         }
9406
9407         switch (tag_no) {
9408         case 0: /* objectIdentifier */
9409             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9410             break;
9411         case 1: /* propertyIdentifier */
9412             offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
9413             break;
9414         case 2: /* propertyArrayIndex */
9415             offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
9416             break;
9417         case 3: /* propertyValue */
9418             offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
9419             break;
9420         case 4: /* Priority (only used for write) */
9421             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
9422             break;
9423         default:
9424             return offset;
9425         }
9426         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9427     }
9428     return offset;
9429 }
9430
9431 static guint
9432 fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9433 {
9434     guint   lastoffset = 0, len;
9435     guint8  tag_no, tag_info;
9436     guint32 lvt;
9437
9438     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9439         lastoffset = offset;
9440         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9441         /* maybe a listOfwriteAccessSpecifications if we spot a closing tag */
9442         if (tag_is_closing(tag_info)) {
9443             offset += len;
9444             continue;
9445         }
9446
9447         switch (tag_no) {
9448         case 0: /* objectIdentifier */
9449             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9450             break;
9451         case 1: /* listOfPropertyValues */
9452             if (tag_is_opening(tag_info)) {
9453                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9454                 offset  = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
9455             } else {
9456                 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
9457             }
9458             break;
9459         default:
9460             return offset;
9461         }
9462         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9463     }
9464     return offset;
9465 }
9466
9467 static guint
9468 fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9469 {
9470     if (offset >= tvb_reported_length(tvb))
9471         return offset;
9472
9473     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9474     return fWriteAccessSpecification(tvb, pinfo, tree, offset);
9475 }
9476
9477 static guint
9478 fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list)
9479 {
9480     guint   lastoffset = 0;
9481     guint8  tag_no, tag_info;
9482     guint32 lvt;
9483
9484     /* set the optional global properties to indicate not-used */
9485     propertyArrayIndex = -1;
9486     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9487         lastoffset = offset;
9488         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9489         if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
9490             return offset;
9491         } else if (tag_is_opening(tag_info)) { /* opening Tag, but not for me */
9492             return offset;
9493         }
9494         switch (tag_no-tagoffset) {
9495         case 0: /* PropertyIdentifier */
9496             offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
9497             break;
9498         case 1: /* propertyArrayIndex */
9499             offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
9500             if (list != 0) break; /* Continue decoding if this may be a list */
9501         default:
9502             lastoffset = offset; /* Set loop end condition */
9503             break;
9504         }
9505         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9506     }
9507     return offset;
9508 }
9509
9510 static guint
9511 fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list)
9512 {
9513     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9514     return fPropertyReference(tvb, pinfo, tree, offset, 0, list);
9515 }
9516
9517 static guint
9518 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9519 {
9520     guint lastoffset = 0;
9521
9522     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9523         lastoffset = offset;
9524
9525         switch (fTagNo(tvb, offset)) {
9526         case 0: /* ObjectIdentifier */
9527             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9528             break;
9529         case 1: /* PropertyIdentifier and propertyArrayIndex */
9530             offset = fPropertyReference(tvb, pinfo, tree, offset, 1, 0);
9531             col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9532         default:
9533             lastoffset = offset; /* Set loop end condition */
9534             break;
9535         }
9536         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9537     }
9538     return offset;
9539 }
9540
9541 #if 0
9542 static guint
9543 fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, guint offset)
9544 {
9545     guint       lastoffset = 0;
9546     guint8      tag_no, tag_info;
9547     guint32     lvt;
9548     proto_tree* subtree = tree;
9549     proto_item* tt;
9550
9551     while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
9552         lastoffset = offset;
9553         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9554         if (tag_is_closing(tag_info)) {
9555             offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
9556                 &tag_no, &tag_info, &lvt);
9557             continue;
9558         }
9559         switch (tag_no) {
9560         case 0: /* ObjectIdentifier */
9561             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9562             break;
9563         case 1: /* PropertyIdentifier */
9564             offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
9565             break;
9566         case 2: /* propertyArrayIndex */
9567             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "property Array Index: ");
9568             break;
9569         case 3:  /* Value */
9570             offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
9571             break;
9572         case 4:  /* Priority */
9573             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
9574             break;
9575         default:
9576             break;
9577         }
9578     }
9579     return offset;
9580 }
9581 #endif
9582
9583 static guint
9584 fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9585 {
9586     char  i = 1, ar[256];
9587     guint lastoffset = 0;
9588
9589     if (propertyArrayIndex > 0) {
9590         /* BACnetARRAY index 0 refers to the length
9591         of the array, not the elements of the array.
9592         BACnetARRAY index -1 is our internal flag that
9593         the optional index was not used.
9594         BACnetARRAY refers to this as all elements of the array.
9595         If the optional index is specified for a BACnetARRAY,
9596         then that specific array element is referenced. */
9597         i = propertyArrayIndex;
9598     }
9599     while (tvb_reported_length_remaining(tvb, offset) > 0) {
9600         /* exit loop if nothing happens inside */
9601         lastoffset = offset;
9602         g_snprintf(ar, sizeof(ar), "%s[%d]: ",
9603             val_to_split_str(87 , 512,
9604                 BACnetPropertyIdentifier,
9605                 ASHRAE_Reserved_Fmt,
9606                 Vendor_Proprietary_Fmt),
9607             i++);
9608         /* DMR Should be fAbstractNSyntax, but that's where we came from! */
9609         offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9610         /* there are only 16 priority array elements */
9611         if (i > 16) {
9612             break;
9613         }
9614         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9615     }
9616
9617     return offset;
9618 }
9619
9620 static guint
9621 fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9622 {
9623     guint lastoffset = 0;
9624
9625     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9626         lastoffset = offset;
9627
9628         switch (fTagNo(tvb, offset)) {
9629         case 0: /* deviceIdentifier - OPTIONAL */
9630             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9631             break;
9632         case 1: /* ObjectIdentifier */
9633             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9634             break;
9635         default:
9636             return offset;
9637         }
9638         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9639     }
9640     return offset;
9641 }
9642
9643 static guint
9644 fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9645 {
9646     guint8 tag_no, tag_info;
9647     guint32 lvt;
9648     guint lastoffset = 0;
9649
9650     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9651         lastoffset = offset;
9652         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9653         /* quit loop if we spot an un-matched closing tag */
9654         if (tag_is_closing(tag_info)) {
9655             break;
9656         }
9657         switch (tag_no) {
9658         case 0: /* calendarEntry */
9659             if (tag_is_opening(tag_info)) {
9660                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9661                 offset  = fCalendarEntry(tvb, pinfo, subtree, offset);
9662                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9663             }
9664             break;
9665         case 1: /* calendarReference */
9666             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9667             break;
9668         case 2: /* list of BACnetTimeValue */
9669             if (tag_is_opening(tag_info)) {
9670                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9671                 offset  = fTimeValue(tvb, pinfo, subtree, offset);
9672                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9673             } else {
9674                 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
9675             }
9676             break;
9677         case 3: /* eventPriority */
9678             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "event priority: ");
9679             break;
9680         default:
9681             return offset;
9682         }
9683         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9684     }
9685     return offset;
9686 }
9687
9688 static guint
9689 fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9690 {
9691     guint   lastoffset = 0, len;
9692     guint8  tag_no, tag_info;
9693     guint32 lvt;
9694
9695     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9696         lastoffset = offset;
9697         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9698         /* maybe a listOfSelectionCriteria if we spot a closing tag */
9699         if (tag_is_closing(tag_info)) {
9700             offset += len;
9701             continue;
9702         }
9703
9704         switch (fTagNo(tvb, offset)) {
9705         case 0: /* propertyIdentifier */
9706             offset  = fPropertyIdentifier(tvb, pinfo, tree, offset);
9707             break;
9708         case 1: /* propertyArrayIndex */
9709             offset  = fPropertyArrayIndex(tvb, pinfo, tree, offset);
9710             break;
9711         case 2: /* relationSpecifier */
9712             offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
9713                 "relation Specifier: ", BACnetRelationSpecifier);
9714             break;
9715         case 3: /* comparisonValue */
9716             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9717             offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
9718             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
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 fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9730 {
9731     guint   lastoffset = 0;
9732     guint8  tag_no, tag_info;
9733     guint32 lvt;
9734
9735     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9736         lastoffset = offset;
9737         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9738         /* quit loop if we spot a closing tag */
9739         if (tag_is_closing(tag_info)) {
9740             break;
9741         }
9742
9743         switch (tag_no) {
9744         case 0: /* selectionLogic */
9745             offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
9746                 "selection Logic: ", BACnetSelectionLogic);
9747             break;
9748         case 1: /* listOfSelectionCriteria */
9749             if (tag_is_opening(tag_info)) {
9750                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9751                 offset  = fSelectionCriteria(tvb, pinfo, subtree, offset);
9752                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9753             } else {
9754                 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
9755             }
9756             break;
9757         default:
9758             return offset;
9759         }
9760         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9761     }
9762     return offset;
9763 }
9764
9765
9766 static guint
9767 fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *subtree, guint offset)
9768 {
9769     guint   lastoffset = 0;
9770     guint8  tag_no, tag_info;
9771     guint32 lvt;
9772
9773     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9774         lastoffset = offset;
9775         fTagHeader (tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9776
9777         if (tag_is_opening(tag_info) && tag_no < 2) {
9778             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9779             switch (tag_no) {
9780             case 0: /* objectSelectionCriteria */
9781                 offset = fObjectSelectionCriteria(tvb, pinfo, subtree, offset);
9782                 break;
9783             case 1: /* listOfPropertyReferences */
9784                 offset = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
9785                 break;
9786             default:
9787                 return offset;
9788             }
9789             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9790         }
9791         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9792     }
9793     return offset;
9794 }
9795
9796 static guint
9797 fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9798 {
9799     guint       lastoffset = 0;
9800     guint8      tag_no, tag_info;
9801     guint32     lvt;
9802     proto_tree *subtree = tree;
9803
9804     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9805         lastoffset = offset;
9806         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9807         switch (tag_no) {
9808         case 0: /* objectIdentifier */
9809             offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9810             break;
9811         case 1: /* listOfPropertyReferences */
9812             if (tag_is_opening(tag_info)) {
9813                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfPropertyReferences");
9814                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9815                 offset  = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
9816             } else if (tag_is_closing(tag_info)) {
9817                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
9818                     &tag_no, &tag_info, &lvt);
9819                 subtree = tree;
9820             } else {
9821                 /* error condition: let caller handle */
9822                 return offset;
9823             }
9824             break;
9825         default:
9826             return offset;
9827         }
9828         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9829     }
9830     return offset;
9831 }
9832
9833 static guint
9834 fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9835 {
9836     guint       lastoffset = 0, len;
9837     guint8      tag_no;
9838     guint8      tag_info;
9839     guint32     lvt;
9840     proto_tree *subtree = tree;
9841
9842     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9843         lastoffset = offset;
9844         len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9845         /* maybe a listOfReadAccessResults if we spot a closing tag here */
9846         if (tag_is_closing(tag_info)) {
9847             offset += len;
9848             if ((tag_no == 4 || tag_no == 5) && (subtree != tree)) subtree = subtree->parent; /* Value and error have extra subtree */
9849             continue;
9850         }
9851
9852         switch (tag_no) {
9853         case 0: /* objectSpecifier */
9854             offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9855             break;
9856         case 1: /* list of Results */
9857             if (tag_is_opening(tag_info)) {
9858                 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfResults");
9859                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9860             } else {
9861                 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
9862             }
9863             break;
9864         case 2: /* propertyIdentifier */
9865             offset = fPropertyIdentifierValue(tvb, pinfo, subtree, offset, 2);
9866             break;
9867         case 5: /* propertyAccessError */
9868             if (tag_is_opening(tag_info)) {
9869                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "propertyAccessError");
9870                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9871                 /* Error Code follows */
9872                 offset  = fError(tvb, pinfo, subtree, offset);
9873             } else {
9874                 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
9875             }
9876             break;
9877         default:
9878             return offset;
9879         }
9880         if (offset == lastoffset) break;     /* nothing happened, exit loop */
9881     }
9882     return offset;
9883 }
9884
9885
9886 static guint
9887 fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9888 {
9889     /* listOfReadAccessResults */
9890     return fReadAccessResult(tvb, pinfo, tree, offset);
9891 }
9892
9893
9894 static guint
9895 fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9896 {
9897     guint   lastoffset = 0;
9898     guint8  tag_no, tag_info;
9899     guint32 lvt;
9900
9901     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9902         lastoffset = offset;
9903         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9904
9905         if (tag_no < 2) {
9906             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9907             switch (tag_no) {
9908             case 0: /* objectSpecifier */
9909                 switch (fTagNo(tvb, offset)) { /* choice of objectType or objectIdentifier */
9910                 case 0: /* objectType */
9911                     offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset, "Object Type: ", BACnetObjectType, 128);
9912                     break;
9913                 case 1: /* objectIdentifier */
9914                     offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9915                     break;
9916                 default:
9917                     break;
9918                 }
9919                 break;
9920             case 1: /* propertyValue */
9921                 if (tag_is_opening(tag_info)) {
9922                     offset = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
9923                 } else {
9924                     expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
9925                 }
9926                 break;
9927             default:
9928                 break;
9929             }
9930             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9931         }
9932         if (offset == lastoffset) break;    /* nothing happened, exit loop */
9933     }
9934     return offset;
9935 }
9936
9937 static guint
9938 fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9939 {
9940     return fObjectIdentifier(tvb, pinfo, tree, offset);
9941 }
9942
9943 static guint
9944 fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9945 {
9946     guint8      tag_no, tag_info;
9947     guint32     lvt;
9948     proto_tree *subtree = tree;
9949
9950     offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
9951
9952     if (tvb_reported_length_remaining(tvb, offset) > 0) {
9953         /* optional range choice */
9954         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9955         if (tag_is_opening(tag_info)) {
9956             subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL,
9957                 val_to_str_const(tag_no, BACnetReadRangeOptions, "unknown range option"));
9958             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9959             switch (tag_no) {
9960             case 3: /* range byPosition */
9961             case 6: /* range bySequenceNumber, 2004 spec */
9962                 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Index: ");
9963                 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
9964                 break;
9965             case 4: /* range byTime - deprecated in 2004 */
9966             case 7: /* 2004 spec */
9967                 offset = fDateTime(tvb, pinfo, subtree, offset, "reference Date/Time: ");
9968                 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
9969                 break;
9970             case 5: /* range timeRange - deprecated in 2004 */
9971                 offset = fDateTime(tvb, pinfo, subtree, offset, "beginning Time: ");
9972                 offset = fDateTime(tvb, pinfo, subtree, offset, "ending Time: ");
9973                 break;
9974             default:
9975                 break;
9976             }
9977             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9978         }
9979     }
9980     return offset;
9981 }
9982
9983 static guint
9984 fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9985 {
9986     guint8      tag_no, tag_info;
9987     guint32     lvt;
9988     proto_tree *subtree = tree;
9989
9990     /* set the optional global properties to indicate not-used */
9991     propertyArrayIndex = -1;
9992     /* objectIdentifier, propertyIdentifier, and
9993        OPTIONAL propertyArrayIndex */
9994     offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
9995     /* resultFlags => BACnetResultFlags ::= BIT STRING */
9996     offset = fBitStringTagVS(tvb, pinfo, tree, offset,
9997         "resultFlags: ",
9998         BACnetResultFlags);
9999     /* itemCount */
10000     offset = fUnsignedTag(tvb, pinfo, subtree, offset, "item Count: ");
10001     /* itemData */
10002     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10003     if (tag_is_opening(tag_info)) {
10004         col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10005         subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "itemData");
10006         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10007         offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10008         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10009     }
10010     /* firstSequenceNumber - OPTIONAL */
10011     if (tvb_reported_length_remaining(tvb, offset) > 0) {
10012         offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "first Sequence Number: ");
10013     }
10014
10015     return offset;
10016 }
10017
10018 static guint
10019 fAccessMethod(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10020 {
10021     guint       lastoffset = 0;
10022     guint32     lvt;
10023     guint8      tag_no, tag_info;
10024     proto_tree* subtree = NULL;
10025
10026     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10027
10028     if (tag_is_opening(tag_info)) {
10029         subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL,
10030             val_to_str_const(tag_no, BACnetFileAccessOption, "invalid access method"));
10031         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10032         offset  = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "invalid option"));
10033         offset  = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileWriteInfo, "unknown option"));
10034
10035         if (tag_no == 1) {
10036             while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
10037                 /* exit loop if nothing happens inside */
10038                 lastoffset = offset;
10039                 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "Record Data: ");
10040             }
10041         }
10042
10043         if ((bacapp_flags & BACAPP_MORE_SEGMENTS) == 0) {
10044             /* More Flag is not set, so we can look for closing tag in this segment */
10045             fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10046             if (tag_is_closing(tag_info)) {
10047                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10048             }
10049         }
10050     }
10051     return offset;
10052 }
10053
10054 static guint
10055 fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10056 {
10057     guint8      tag_no, tag_info;
10058     guint32     lvt;
10059     proto_tree *subtree = tree;
10060
10061     offset = fObjectIdentifier(tvb, pinfo, tree, offset);
10062
10063     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10064
10065     if (tag_is_opening(tag_info)) {
10066         subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL,
10067                         val_to_str_const(tag_no, BACnetFileAccessOption, "unknown access method"));
10068         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10069         offset  = fSignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
10070         offset  = fUnsignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileRequestCount, "unknown option"));
10071         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10072     }
10073     return offset;
10074 }
10075
10076 static guint
10077 fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10078 {
10079
10080     offset = fObjectIdentifier(tvb, pinfo, tree, offset); /* file Identifier */
10081     offset = fAccessMethod(tvb, pinfo, tree, offset);
10082
10083     return offset;
10084 }
10085
10086 static guint
10087 fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10088 {
10089     guint tag_no = fTagNo(tvb, offset);
10090     return fSignedTag(tvb, pinfo, tree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
10091 }
10092
10093 static guint
10094 fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10095 {
10096     offset = fApplicationTypes(tvb, pinfo, tree, offset, "End Of File: ");
10097     offset = fAccessMethod(tvb, pinfo, tree, offset);
10098
10099     return offset;
10100 }
10101
10102 static guint
10103 fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
10104 {
10105     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10106     return fReadAccessSpecification(tvb, pinfo, subtree, offset);
10107 }
10108
10109 static guint
10110 fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10111 {
10112     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10113     return fReadAccessResult(tvb, pinfo, tree, offset);
10114 }
10115
10116 static guint
10117 fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
10118 {
10119     if (tvb_reported_length_remaining(tvb, offset) <= 0)
10120         return offset;
10121
10122     switch (service_choice) {
10123     case 0: /* acknowledgeAlarm */
10124         offset = fAcknowledgeAlarmRequest(tvb, pinfo, tree, offset);
10125         break;
10126     case 1: /* confirmedCOVNotification */
10127         offset = fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
10128         break;
10129     case 2: /* confirmedEventNotification */
10130         offset = fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
10131         break;
10132     case 3: /* confirmedGetAlarmSummary conveys no parameters */
10133         break;
10134     case 4: /* getEnrollmentSummaryRequest */
10135         offset = fGetEnrollmentSummaryRequest(tvb, pinfo, tree, offset);
10136         break;
10137     case 5: /* subscribeCOVRequest */
10138         offset = fSubscribeCOVRequest(tvb, pinfo, tree, offset);
10139         break;
10140     case 6: /* atomicReadFile-Request */
10141         offset = fAtomicReadFileRequest(tvb, pinfo, tree, offset);
10142         break;
10143     case 7: /* atomicWriteFile-Request */
10144         offset = fAtomicWriteFileRequest(tvb, pinfo, tree, offset);
10145         break;
10146     case 8: /* AddListElement-Request */
10147         offset = fAddListElementRequest(tvb, pinfo, tree, offset);
10148         break;
10149     case 9: /* removeListElement-Request */
10150         offset = fRemoveListElementRequest(tvb, pinfo, tree, offset);
10151         break;
10152     case 10: /* createObjectRequest */
10153         offset = fCreateObjectRequest(tvb, pinfo, tree, offset);
10154         break;
10155     case 11: /* deleteObject */
10156         offset = fDeleteObjectRequest(tvb, pinfo, tree, offset);
10157         break;
10158     case 12:
10159         offset = fReadPropertyRequest(tvb, pinfo, tree, offset);
10160         break;
10161     case 13:
10162         offset = fReadPropertyConditionalRequest(tvb, pinfo, tree, offset);
10163         break;
10164     case 14:
10165         offset = fReadPropertyMultipleRequest(tvb, pinfo, tree, offset);
10166         break;
10167     case 15:
10168         offset = fWritePropertyRequest(tvb, pinfo, tree, offset);
10169         break;
10170     case 16:
10171         offset = fWritePropertyMultipleRequest(tvb, pinfo, tree, offset);
10172         break;
10173     case 17:
10174         offset = fDeviceCommunicationControlRequest(tvb, pinfo, tree, offset);
10175         break;
10176     case 18:
10177         offset = fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
10178         break;
10179     case 19:
10180         offset = fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
10181         break;
10182     case 20:
10183         offset = fReinitializeDeviceRequest(tvb, pinfo, tree, offset);
10184         break;
10185     case 21:
10186         offset = fVtOpenRequest(tvb, pinfo, tree, offset);
10187         break;
10188     case 22:
10189         offset = fVtCloseRequest(tvb, pinfo, tree, offset);
10190         break;
10191     case 23:
10192         offset = fVtDataRequest(tvb, pinfo, tree, offset);
10193         break;
10194     case 24:
10195         offset = fAuthenticateRequest(tvb, pinfo, tree, offset);
10196         break;
10197     case 25:
10198         offset = fRequestKeyRequest(tvb, pinfo, tree, offset);
10199         break;
10200     case 26:
10201         offset = fReadRangeRequest(tvb, pinfo, tree, offset);
10202         break;
10203     case 27:
10204         offset = fLifeSafetyOperationRequest(tvb, pinfo, tree, offset, NULL);
10205         break;
10206     case 28:
10207         offset = fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
10208         break;
10209     case 29:
10210         offset = fGetEventInformationRequest(tvb, pinfo, tree, offset);
10211         break;
10212     default:
10213         return offset;
10214     }
10215     return offset;
10216 }
10217
10218 static guint
10219 fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
10220 {
10221     if (tvb_reported_length_remaining(tvb, offset) <= 0)
10222         return offset;
10223
10224     switch (service_choice) {
10225     case 3: /* confirmedEventNotificationAck */
10226         offset = fGetAlarmSummaryAck(tvb, pinfo, tree, offset);
10227         break;
10228     case 4: /* getEnrollmentSummaryAck */
10229         offset = fGetEnrollmentSummaryAck(tvb, pinfo, tree, offset);
10230         break;
10231     case 6: /* atomicReadFile */
10232         offset = fAtomicReadFileAck(tvb, pinfo, tree, offset);
10233         break;
10234     case 7: /* atomicReadFileAck */
10235         offset = fAtomicWriteFileAck(tvb, pinfo, tree, offset);
10236         break;
10237     case 10: /* createObject */
10238         offset = fCreateObjectAck(tvb, pinfo, tree, offset);
10239         break;
10240     case 12:
10241         offset = fReadPropertyAck(tvb, pinfo, tree, offset);
10242         break;
10243     case 13:
10244         offset = fReadPropertyConditionalAck(tvb, pinfo, tree, offset);
10245         break;
10246     case 14:
10247         offset = fReadPropertyMultipleAck(tvb, pinfo, tree, offset);
10248         break;
10249     case 18:
10250         offset = fConfirmedPrivateTransferAck(tvb, pinfo, tree, offset);
10251         break;
10252     case 21:
10253         offset = fVtOpenAck(tvb, pinfo, tree, offset);
10254         break;
10255     case 23:
10256         offset = fVtDataAck(tvb, pinfo, tree, offset);
10257         break;
10258     case 24:
10259         offset = fAuthenticateAck(tvb, pinfo, tree, offset);
10260         break;
10261     case 26:
10262         offset = fReadRangeAck(tvb, pinfo, tree, offset);
10263         break;
10264     case 29:
10265         offset = fGetEventInformationACK(tvb, pinfo, tree, offset);
10266         break;
10267     default:
10268         return offset;
10269     }
10270     return offset;
10271 }
10272
10273 static guint
10274 fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10275 {
10276     /* BACnetObjectIdentifier */
10277     offset = fApplicationTypes(tvb, pinfo, tree, offset, "BACnet Object Identifier: ");
10278
10279     /* MaxAPDULengthAccepted */
10280     offset = fApplicationTypes(tvb, pinfo, tree, offset, "Maximum ADPU Length Accepted: ");
10281
10282     /* segmentationSupported */
10283     offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
10284         "Segmentation Supported: ", BACnetSegmentation);
10285
10286     /* vendor ID */
10287     return fVendorIdentifier(tvb, pinfo, tree, offset);
10288 }
10289
10290 static guint
10291 fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10292 {
10293     /* BACnetDeviceIdentifier */
10294     offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device Identifier: ");
10295
10296     /* BACnetObjectIdentifier */
10297     offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
10298
10299     /* ObjectName */
10300     return fApplicationTypes(tvb, pinfo, tree, offset, "Object Name: ");
10301
10302 }
10303
10304 static guint
10305 fWhoIsRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, guint offset)
10306 {
10307     guint   lastoffset = 0;
10308     guint   val;
10309     guint8  tag_len;
10310
10311     guint8  tag_no, tag_info;
10312     guint32 lvt;
10313
10314     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10315         lastoffset = offset;
10316
10317         tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10318
10319         switch (tag_no) {
10320         case 0:
10321             /* DeviceInstanceRangeLowLimit Optional */
10322             if (col_get_writable(pinfo->cinfo) && fUnsigned32(tvb, offset+tag_len, lvt, &val))
10323                 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
10324             offset = fDevice_Instance(tvb, pinfo, tree, offset,
10325                 hf_Device_Instance_Range_Low_Limit);
10326             break;
10327         case 1:
10328             /* DeviceInstanceRangeHighLimit Optional but
10329                 required if DeviceInstanceRangeLowLimit is there */
10330             if (col_get_writable(pinfo->cinfo) && fUnsigned32(tvb, offset+tag_len, lvt, &val))
10331                 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
10332             offset = fDevice_Instance(tvb, pinfo, tree, offset,
10333                 hf_Device_Instance_Range_High_Limit);
10334             break;
10335         default:
10336             return offset;
10337         }
10338         if (offset == lastoffset) break;     /* nothing happened, exit loop */
10339     }
10340     return offset;
10341 }
10342
10343 static guint
10344 fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
10345 {
10346     if (tvb_reported_length_remaining(tvb, offset) <= 0)
10347         return offset;
10348
10349     switch (service_choice) {
10350     case 0: /* I-Am-Request */
10351         offset = fIAmRequest(tvb, pinfo, tree, offset);
10352         break;
10353     case 1: /* i-Have Request */
10354         offset = fIHaveRequest(tvb, pinfo, tree, offset);
10355     break;
10356     case 2: /* unconfirmedCOVNotification */
10357         offset = fUnconfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
10358         break;
10359     case 3: /* unconfirmedEventNotification */
10360         offset = fUnconfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
10361         break;
10362     case 4: /* unconfirmedPrivateTransfer */
10363         offset = fUnconfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
10364         break;
10365     case 5: /* unconfirmedTextMessage */
10366         offset = fUnconfirmedTextMessageRequest(tvb, pinfo, tree, offset);
10367         break;
10368     case 206: /* utc-time-synchronization-recipients */
10369     case 6: /* timeSynchronization */
10370         offset = fTimeSynchronizationRequest(tvb, pinfo, tree, offset);
10371         break;
10372     case 7: /* who-Has */
10373         offset = fWhoHas(tvb, pinfo, tree, offset);
10374         break;
10375     case 8: /* who-Is */
10376         offset = fWhoIsRequest(tvb, pinfo, tree, offset);
10377         break;
10378     case 9: /* utcTimeSynchronization */
10379         offset = fUTCTimeSynchronizationRequest(tvb, pinfo, tree, offset);
10380         break;
10381     default:
10382         break;
10383     }
10384     return offset;
10385 }
10386
10387 static guint
10388 fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset, guint8 ack,
10389         gint *svc, proto_item **tt)
10390 {
10391     proto_item *tc;
10392     proto_tree *bacapp_tree_control;
10393     gint        tmp;
10394     guint       extra = 2;
10395
10396     bacapp_seq = 0;
10397     tmp = (gint) tvb_get_guint8(tvb, offset);
10398     bacapp_flags = tmp & 0x0f;
10399
10400     if (ack == 0) {
10401         extra = 3;
10402     }
10403     *svc = (gint) tvb_get_guint8(tvb, offset+extra);
10404     if (bacapp_flags & 0x08)
10405         *svc = (gint) tvb_get_guint8(tvb, offset+extra+2);
10406
10407     proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
10408     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_pduflags, tvb, offset, 1, ENC_BIG_ENDIAN);
10409     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp_control);
10410
10411     proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, ENC_BIG_ENDIAN);
10412     proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, ENC_BIG_ENDIAN);
10413     if (ack == 0) { /* The following are for ConfirmedRequest, not Complex ack */
10414         proto_tree_add_item(bacapp_tree_control, hf_bacapp_SA, tvb, offset++, 1, ENC_BIG_ENDIAN);
10415         proto_tree_add_item(bacapp_tree, hf_bacapp_response_segments, tvb,
10416                             offset, 1, ENC_BIG_ENDIAN);
10417         proto_tree_add_item(bacapp_tree, hf_bacapp_max_adpu_size, tvb,
10418                             offset, 1, ENC_BIG_ENDIAN);
10419     }
10420     offset++;
10421     proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
10422     if (bacapp_flags & 0x08) {
10423         bacapp_seq = tvb_get_guint8(tvb, offset);
10424         proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
10425             offset++, 1, ENC_BIG_ENDIAN);
10426         proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
10427             offset++, 1, ENC_BIG_ENDIAN);
10428     }
10429     *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
10430                   offset++, 1, ENC_BIG_ENDIAN);
10431     return offset;
10432 }
10433
10434 static guint
10435 fContinueConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
10436 {   /* BACnet-Confirmed-Request */
10437     /* ASHRAE 135-2001 20.1.2 */
10438
10439     return fConfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, svc);
10440 }
10441
10442 static guint
10443 fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10444 {   /* BACnet-Confirmed-Request */
10445     /* ASHRAE 135-2001 20.1.2 */
10446     gint        svc;
10447     proto_item *tt = 0;
10448
10449     offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 0, &svc, &tt);
10450     return fContinueConfirmedRequestPDU(tvb, pinfo, bacapp_tree, offset, svc);
10451 }
10452
10453 static guint
10454 fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10455 {   /* BACnet-Unconfirmed-Request-PDU */
10456     /* ASHRAE 135-2001 20.1.3 */
10457
10458     gint tmp;
10459
10460     proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10461
10462     tmp = tvb_get_guint8(tvb, offset);
10463     proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
10464         offset++, 1, ENC_BIG_ENDIAN);
10465     /* Service Request follows... Variable Encoding 20.2ff */
10466     return fUnconfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, tmp);
10467 }
10468
10469 static guint
10470 fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10471 {   /* BACnet-Simple-Ack-PDU */
10472     /* ASHRAE 135-2001 20.1.4 */
10473
10474     proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10475
10476     proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
10477                 offset++, 1, ENC_BIG_ENDIAN);
10478     proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
10479                 offset++, 1, ENC_BIG_ENDIAN);
10480
10481     return offset;
10482 }
10483
10484 static guint
10485 fContinueComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
10486 {   /* BACnet-Complex-Ack-PDU */
10487     /* ASHRAE 135-2001 20.1.5 */
10488
10489     /* Service ACK follows... */
10490     return fConfirmedServiceAck(tvb, pinfo, bacapp_tree, offset, svc);
10491 }
10492
10493 static guint
10494 fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10495 {   /* BACnet-Complex-Ack-PDU */
10496     /* ASHRAE 135-2001 20.1.5 */
10497     gint        svc;
10498     proto_item *tt = 0;
10499
10500     offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 1, &svc, &tt);
10501     return fContinueComplexAckPDU(tvb, pinfo, bacapp_tree, offset, svc);
10502 }
10503
10504 static guint
10505 fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10506 {   /* BACnet-SegmentAck-PDU */
10507     /* ASHRAE 135-2001 20.1.6 */
10508
10509     proto_item *tc;
10510     proto_tree *bacapp_tree_control;
10511
10512     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
10513     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10514
10515     proto_tree_add_item(bacapp_tree_control, hf_bacapp_NAK, tvb, offset, 1, ENC_BIG_ENDIAN);
10516     proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
10517     proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10518                 offset++, 1, ENC_BIG_ENDIAN);
10519     proto_tree_add_item(bacapp_tree_control, hf_bacapp_sequence_number, tvb,
10520                 offset++, 1, ENC_BIG_ENDIAN);
10521     proto_tree_add_item(bacapp_tree_control, hf_bacapp_window_size, tvb,
10522                 offset++, 1, ENC_BIG_ENDIAN);
10523     return offset;
10524 }
10525
10526 static guint
10527 fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10528 {
10529     guint8  tag_info   = 0;
10530     guint8  parsed_tag = 0;
10531     guint32 lvt        = 0;
10532
10533     offset += fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
10534     offset  = fError(tvb, pinfo, tree, offset);
10535     return offset + fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
10536 }
10537
10538 static guint
10539 fConfirmedPrivateTransferError(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     proto_tree *subtree           = tree;
10545
10546     guint       vendor_identifier = 0;
10547     guint       service_number    = 0;
10548     guint8      tag_len           = 0;
10549
10550     while (tvb_reported_length_remaining(tvb, offset) > 0) {
10551         /* exit loop if nothing happens inside */
10552         lastoffset = offset;
10553         tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10554         switch (tag_no) {
10555         case 0: /* errorType */
10556             offset = fContextTaggedError(tvb, pinfo, subtree, offset);
10557             break;
10558         case 1: /* vendorID */
10559             fUnsigned32(tvb, offset+tag_len, lvt, &vendor_identifier);
10560             if (col_get_writable(pinfo->cinfo))
10561                 col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ",    vendor_identifier);
10562             offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
10563             break;
10564         case 2: /* serviceNumber */
10565             fUnsigned32(tvb, offset+tag_len, lvt, &service_number);
10566             if (col_get_writable(pinfo->cinfo))
10567                 col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ",   service_number);
10568             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
10569             break;
10570         case 3: /* errorParameters */
10571             if (tag_is_opening(tag_info)) {
10572                 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1,
10573                     ett_bacapp_value, NULL, "error Parameters");
10574                 propertyIdentifier = -1;
10575                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10576                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10577             } else if (tag_is_closing(tag_info)) {
10578                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
10579                     &tag_no, &tag_info, &lvt);
10580                 subtree = tree;
10581             } else {
10582                 /* error condition: let caller handle */
10583                 return offset;
10584             }
10585             break;
10586         default:
10587             return offset;
10588         }
10589         if (offset == lastoffset) break;     /* nothing happened, exit loop */
10590     }
10591     return offset;
10592 }
10593
10594 static guint
10595 fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10596 {
10597     guint lastoffset = 0;
10598
10599     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10600         lastoffset = offset;
10601         switch (fTagNo(tvb, offset)) {
10602         case 0: /* errorType */
10603             offset = fContextTaggedError(tvb, pinfo, tree, offset);
10604             break;
10605         case 1: /* firstFailedElementNumber */
10606             offset = fUnsignedTag(tvb, pinfo, tree, offset, "first failed element number: ");
10607             break;
10608         default:
10609             return offset;
10610         }
10611         if (offset == lastoffset) break;     /* nothing happened, exit loop */
10612     }
10613     return offset;
10614 }
10615
10616 static guint
10617 fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10618 {
10619     /* Identical to CreateObjectError */
10620     return fCreateObjectError(tvb, pinfo, tree, offset);
10621 }
10622
10623 static guint
10624 fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10625 {
10626     guint8  tag_no = 0, tag_info = 0;
10627     guint32 lvt = 0;
10628
10629     if (fTagNo(tvb, offset) == 0) {
10630         /* errorType */
10631         offset = fContextTaggedError(tvb, pinfo, tree, offset);
10632         if (fTagNo(tvb, offset) == 1) {
10633             /* listOfVTSessionIdentifiers [OPTIONAL] */
10634             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10635             offset  = fVtCloseRequest(tvb, pinfo, tree, offset);
10636             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10637         }
10638     }
10639     /* should report bad packet if initial tag wasn't 0 */
10640     return offset;
10641 }
10642
10643 static guint
10644 fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10645 {
10646     guint   lastoffset = 0;
10647     guint8  tag_no     = 0, tag_info = 0;
10648     guint32 lvt        = 0;
10649
10650     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10651     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10652         lastoffset = offset;
10653         switch (fTagNo(tvb, offset)) {
10654         case 0: /* errorType */
10655             offset = fContextTaggedError(tvb, pinfo, tree, offset);
10656             break;
10657         case 1: /* firstFailedWriteAttempt */
10658             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10659             offset  = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
10660             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10661             break;
10662         default:
10663             return offset;
10664         }
10665         if (offset == lastoffset) break;     /* nothing happened, exit loop */
10666     }
10667     return offset;
10668 }
10669
10670 static guint
10671 fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10672 {
10673     offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
10674                            "error Class: ", BACnetErrorClass, 64);
10675     return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
10676                          "error Code: ", BACnetErrorCode, 256);
10677 }
10678
10679 static guint
10680 fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service)
10681 {
10682     switch (service) {
10683     case 8:  /* no break here !!!! */
10684     case 9:
10685         offset = fChangeListError(tvb, pinfo, tree, offset);
10686         break;
10687     case 10:
10688         offset = fCreateObjectError(tvb, pinfo, tree, offset);
10689         break;
10690     case 16:
10691         offset = fWritePropertyMultipleError(tvb, pinfo, tree, offset);
10692         break;
10693     case 18:
10694         offset = fConfirmedPrivateTransferError(tvb, pinfo, tree, offset);
10695         break;
10696     case 22:
10697         offset = fVTCloseError(tvb, pinfo, tree, offset);
10698         break;
10699     default:
10700         return fError(tvb, pinfo, tree, offset);
10701     }
10702     return offset;
10703 }
10704
10705 static guint
10706 fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10707 {   /* BACnet-Error-PDU */
10708     /* ASHRAE 135-2001 20.1.7 */
10709
10710     proto_item *tc;
10711     proto_tree *bacapp_tree_control;
10712     guint8      tmp;
10713
10714     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10715     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10716
10717     proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10718                 offset++, 1, ENC_BIG_ENDIAN);
10719     tmp = tvb_get_guint8(tvb, offset);
10720     proto_tree_add_item(bacapp_tree_control, hf_bacapp_service, tvb,
10721                  offset++, 1, ENC_BIG_ENDIAN);
10722     /* Error Handling follows... */
10723     return fBACnetError(tvb, pinfo, bacapp_tree, offset, tmp);
10724 }
10725
10726 static guint
10727 fRejectPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10728 {   /* BACnet-Reject-PDU */
10729     /* ASHRAE 135-2001 20.1.8 */
10730
10731     proto_item *tc;
10732     proto_tree *bacapp_tree_control;
10733
10734     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10735     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10736
10737     proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10738                 offset++, 1, ENC_BIG_ENDIAN);
10739     proto_tree_add_item(bacapp_tree_control, hf_BACnetRejectReason, tvb,
10740                 offset++, 1, ENC_BIG_ENDIAN);
10741     return offset;
10742 }
10743
10744 static guint
10745 fAbortPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10746 {   /* BACnet-Abort-PDU */
10747     /* ASHRAE 135-2001 20.1.9 */
10748
10749     proto_item *tc;
10750     proto_tree *bacapp_tree_control;
10751
10752     tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
10753     bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10754
10755     proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
10756     proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10757                 offset++, 1, ENC_BIG_ENDIAN);
10758     proto_tree_add_item(bacapp_tree_control, hf_BACnetAbortReason, tvb,
10759                 offset++, 1, ENC_BIG_ENDIAN);
10760     return offset;
10761 }
10762
10763 static guint
10764 do_the_dissection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
10765 {
10766     guint8 flag, bacapp_type;
10767     guint  offset = 0;
10768
10769     flag = (gint) tvb_get_guint8(tvb, 0);
10770     bacapp_type = (flag >> 4) & 0x0f;
10771
10772     if (tvb == NULL) {
10773         return 0;
10774     }
10775
10776     /* ASHRAE 135-2001 20.1.1 */
10777     switch (bacapp_type) {
10778     case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST: /* BACnet-Confirmed-Service-Request */
10779         offset = fConfirmedRequestPDU(tvb, pinfo, tree, offset);
10780         break;
10781     case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:   /* BACnet-Unconfirmed-Request-PDU */
10782         offset = fUnconfirmedRequestPDU(tvb, pinfo, tree, offset);
10783         break;
10784     case BACAPP_TYPE_SIMPLE_ACK:    /* BACnet-Simple-Ack-PDU */
10785         offset = fSimpleAckPDU(tvb, pinfo, tree, offset);
10786         break;
10787     case BACAPP_TYPE_COMPLEX_ACK:   /* BACnet-Complex-Ack-PDU */
10788         offset = fComplexAckPDU(tvb, pinfo, tree, offset);
10789         break;
10790     case BACAPP_TYPE_SEGMENT_ACK:   /* BACnet-SegmentAck-PDU */
10791         offset = fSegmentAckPDU(tvb, pinfo, tree, offset);
10792         break;
10793     case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
10794         offset = fErrorPDU(tvb, pinfo, tree, offset);
10795         break;
10796     case BACAPP_TYPE_REJECT:    /* BACnet-Reject-PDU */
10797         offset = fRejectPDU(tvb, pinfo, tree, offset);
10798         break;
10799     case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
10800         offset = fAbortPDU(tvb, pinfo, tree, offset);
10801         break;
10802     }
10803     return offset;
10804 }
10805
10806 static void
10807 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
10808 {
10809     guint8      flag, bacapp_type;
10810     guint       save_fragmented  = FALSE, data_offset = 0, /*bacapp_apdu_size,*/ fragment = FALSE;
10811     tvbuff_t   *new_tvb          = NULL;
10812     guint       offset           = 0;
10813     guint8      bacapp_seqno     = 0;
10814     guint8      bacapp_service, bacapp_reason/*, bacapp_prop_win_size*/;
10815     guint8      bacapp_invoke_id = 0;
10816     proto_item *ti;
10817     proto_tree *bacapp_tree      = NULL;
10818
10819     gint        svc = 0;
10820     proto_item *tt  = 0;
10821     gint8       ack = 0;
10822
10823     /* Strings for BACnet Statistics */
10824     const gchar errstr[]       = "ERROR: ";
10825     const gchar rejstr[]       = "REJECTED: ";
10826     const gchar abortstr[]     = "ABORTED: ";
10827     const gchar sackstr[]      = " (SimpleAck)";
10828     const gchar cackstr[]      = " (ComplexAck)";
10829     const gchar uconfsreqstr[] = " (Unconfirmed Service Request)";
10830     const gchar confsreqstr[]  = " (Confirmed Service Request)";
10831
10832     col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
10833     col_clear(pinfo->cinfo, COL_INFO);
10834
10835     flag = tvb_get_guint8(tvb, 0);
10836     bacapp_type = (flag >> 4) & 0x0f;
10837
10838     /* show some descriptive text in the INFO column */
10839     col_add_fstr(pinfo->cinfo, COL_INFO, "%-16s",
10840         val_to_str_const(bacapp_type, BACnetTypeName, "# unknown APDU #"));
10841
10842     bacinfo.service_type = NULL;
10843     bacinfo.invoke_id = NULL;
10844     bacinfo.instance_ident = NULL;
10845     bacinfo.object_ident = NULL;
10846
10847     switch (bacapp_type) {
10848     case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
10849         /* segmented messages have 2 additional bytes */
10850         if (flag & BACAPP_SEGMENTED_REQUEST) {
10851             fragment = TRUE;
10852             ack = 0;
10853             /* bacapp_apdu_size = fGetMaxAPDUSize(tvb_get_guint8(tvb, offset + 1)); */ /* has 16 values, reserved are 50 Bytes */
10854             bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
10855             bacapp_seqno = tvb_get_guint8(tvb, offset + 3);
10856             /* bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 4); */
10857             bacapp_service = tvb_get_guint8(tvb, offset + 5);
10858             data_offset = 6;
10859         } else {
10860             bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
10861             bacapp_service = tvb_get_guint8(tvb, offset + 3);
10862         }
10863         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ",
10864                         val_to_str_const(bacapp_service,
10865                                          BACnetConfirmedServiceChoice,
10866                                          bacapp_unknown_service_str),
10867                         bacapp_invoke_id);
10868
10869         updateBacnetInfoValue(BACINFO_INVOKEID,
10870                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10871
10872         updateBacnetInfoValue(BACINFO_SERVICE,
10873                               wmem_strconcat(wmem_packet_scope(),
10874                                              val_to_str_const(bacapp_service,
10875                                                               BACnetConfirmedServiceChoice,
10876                                                               bacapp_unknown_service_str),
10877                                              confsreqstr, NULL));
10878         break;
10879     case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
10880         bacapp_service = tvb_get_guint8(tvb, offset + 1);
10881         col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
10882                         val_to_str_const(bacapp_service,
10883                                          BACnetUnconfirmedServiceChoice,
10884                                          bacapp_unknown_service_str));
10885
10886         updateBacnetInfoValue(BACINFO_SERVICE,
10887                               wmem_strconcat(wmem_packet_scope(),
10888                                              val_to_str_const(bacapp_service,
10889                                                               BACnetUnconfirmedServiceChoice,
10890                                                               bacapp_unknown_service_str),
10891                                              uconfsreqstr, NULL));
10892         break;
10893     case BACAPP_TYPE_SIMPLE_ACK:
10894         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10895         bacapp_service = tvb_get_guint8(tvb, offset + 2);
10896         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10897                         val_to_str_const(bacapp_service,
10898                                          BACnetConfirmedServiceChoice,
10899                                          bacapp_unknown_service_str),
10900                         bacapp_invoke_id);
10901
10902         updateBacnetInfoValue(BACINFO_INVOKEID,
10903                               wmem_strdup_printf(wmem_packet_scope(),
10904                                                  "Invoke ID: %d", bacapp_invoke_id));
10905
10906         updateBacnetInfoValue(BACINFO_SERVICE,
10907                               wmem_strconcat(wmem_packet_scope(),
10908                                              val_to_str_const(bacapp_service,
10909                                                               BACnetConfirmedServiceChoice,
10910                                                               bacapp_unknown_service_str),
10911                                              sackstr, NULL));
10912         break;
10913     case BACAPP_TYPE_COMPLEX_ACK:
10914         /* segmented messages have 2 additional bytes */
10915         if (flag & BACAPP_SEGMENTED_REQUEST) {
10916             fragment = TRUE;
10917             ack = 1;
10918             /* bacapp_apdu_size = fGetMaxAPDUSize(0); */ /* has minimum of 50 Bytes */
10919             bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10920             bacapp_seqno = tvb_get_guint8(tvb, offset + 2);
10921             /* bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 3); */
10922             bacapp_service = tvb_get_guint8(tvb, offset + 4);
10923             data_offset = 5;
10924         } else {
10925             bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10926             bacapp_service = tvb_get_guint8(tvb, offset + 2);
10927         }
10928         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10929                         val_to_str_const(bacapp_service,
10930                                          BACnetConfirmedServiceChoice,
10931                                          bacapp_unknown_service_str),
10932                         bacapp_invoke_id);
10933
10934         updateBacnetInfoValue(BACINFO_INVOKEID,
10935                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10936
10937         updateBacnetInfoValue(BACINFO_SERVICE,
10938                               wmem_strconcat(wmem_packet_scope(),
10939                                              val_to_str_const(bacapp_service,
10940                                                               BACnetConfirmedServiceChoice,
10941                                                               bacapp_unknown_service_str),
10942                                              cackstr, NULL));
10943         break;
10944     case BACAPP_TYPE_SEGMENT_ACK:
10945         /* nothing more to add */
10946         break;
10947     case BACAPP_TYPE_ERROR:
10948         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10949         bacapp_service = tvb_get_guint8(tvb, offset + 2);
10950         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10951                         val_to_str_const(bacapp_service,
10952                                          BACnetConfirmedServiceChoice,
10953                                          bacapp_unknown_service_str),
10954                         bacapp_invoke_id);
10955
10956         updateBacnetInfoValue(BACINFO_INVOKEID,
10957                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10958
10959         updateBacnetInfoValue(BACINFO_SERVICE,
10960                               wmem_strconcat(wmem_packet_scope(),
10961                                              errstr,
10962                                              val_to_str_const(bacapp_service,
10963                                                               BACnetConfirmedServiceChoice,
10964                                                               bacapp_unknown_service_str),
10965                                              NULL));
10966         break;
10967     case BACAPP_TYPE_REJECT:
10968         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10969         bacapp_reason = tvb_get_guint8(tvb, offset + 2);
10970         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10971                         val_to_split_str(bacapp_reason,
10972                                          64,
10973                                          BACnetRejectReason,
10974                                          ASHRAE_Reserved_Fmt,
10975                                          Vendor_Proprietary_Fmt), bacapp_invoke_id);
10976
10977         updateBacnetInfoValue(BACINFO_INVOKEID,
10978                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10979
10980         updateBacnetInfoValue(BACINFO_SERVICE,
10981                               wmem_strconcat(wmem_packet_scope(), rejstr,
10982                                              val_to_split_str(bacapp_reason, 64,
10983                                                               BACnetRejectReason,
10984                                                               ASHRAE_Reserved_Fmt,
10985                                                               Vendor_Proprietary_Fmt),
10986                                              NULL));
10987         break;
10988     case BACAPP_TYPE_ABORT:
10989         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10990         bacapp_reason = tvb_get_guint8(tvb, offset + 2);
10991         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10992                         val_to_split_str(bacapp_reason,
10993                                          64,
10994                                          BACnetAbortReason,
10995                                          ASHRAE_Reserved_Fmt,
10996                                          Vendor_Proprietary_Fmt), bacapp_invoke_id);
10997
10998         updateBacnetInfoValue(BACINFO_INVOKEID,
10999                               wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
11000
11001         updateBacnetInfoValue(BACINFO_SERVICE,
11002                               wmem_strconcat(wmem_packet_scope(), abortstr,
11003                                              val_to_split_str(bacapp_reason,
11004                                                               64,
11005                                                               BACnetAbortReason,
11006                                                               ASHRAE_Reserved_Fmt,
11007                                                               Vendor_Proprietary_Fmt),
11008                                              NULL));
11009         break;
11010         /* UNKNOWN */
11011     default:
11012         /* nothing more to add */
11013         break;
11014     }
11015
11016     save_fragmented = pinfo->fragmented;
11017
11018     ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, ENC_NA);
11019     bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
11020
11021     if (!fragment)
11022         do_the_dissection(tvb, pinfo, bacapp_tree);
11023     else
11024         fStartConfirmed(tvb, pinfo, bacapp_tree, offset, ack, &svc, &tt);
11025             /* not resetting the offset so the remaining can be done */
11026
11027     if (fragment) { /* fragmented */
11028         fragment_head *frag_msg;
11029
11030         pinfo->fragmented = TRUE;
11031
11032         frag_msg = fragment_add_seq_check(&msg_reassembly_table,
11033             tvb, data_offset,
11034             pinfo,
11035             bacapp_invoke_id,      /* ID for fragments belonging together */
11036             NULL,
11037             bacapp_seqno,          /* fragment sequence number */
11038             tvb_reported_length_remaining(tvb, data_offset), /* fragment length - to the end */
11039             flag & BACAPP_MORE_SEGMENTS); /* Last fragment reached? */
11040         new_tvb = process_reassembled_data(tvb, data_offset, pinfo,
11041                 "Reassembled BACapp", frag_msg, &msg_frag_items,
11042                 NULL, tree);
11043
11044         if (new_tvb) { /* Reassembled */
11045             col_append_str(pinfo->cinfo, COL_INFO,
11046                            " (Message Reassembled)");
11047         } else { /* Not last packet of reassembled Short Message */
11048             col_append_fstr(pinfo->cinfo, COL_INFO,
11049                             " (Message fragment %u)", bacapp_seqno);
11050         }
11051         if (new_tvb) { /* take it all */
11052             switch (bacapp_type) {
11053             case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
11054                 fContinueConfirmedRequestPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
11055                 break;
11056             case BACAPP_TYPE_COMPLEX_ACK:
11057                 fContinueComplexAckPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
11058                 break;
11059             default:
11060                 /* do nothing */
11061                 break;
11062             }
11063         }
11064     }
11065
11066     pinfo->fragmented = save_fragmented;
11067
11068     /* tapping */
11069     tap_queue_packet(bacapp_tap, pinfo, &bacinfo);
11070 }
11071
11072 static void
11073 bacapp_init_routine(void)
11074 {
11075     reassembly_table_init(&msg_reassembly_table,
11076                           &addresses_reassembly_table_functions);
11077 }
11078
11079 void
11080 proto_register_bacapp(void)
11081 {
11082     static hf_register_info hf[] = {
11083         { &hf_bacapp_type,
11084           { "APDU Type",           "bacapp.type",
11085             FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, NULL, HFILL }
11086         },
11087         { &hf_bacapp_pduflags,
11088           { "PDU Flags",          "bacapp.pduflags",
11089             FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }
11090         },
11091         { &hf_bacapp_SEG,
11092           { "Segmented Request",           "bacapp.segmented_request",
11093             FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, NULL, HFILL }
11094         },
11095         { &hf_bacapp_MOR,
11096           { "More Segments",           "bacapp.more_segments",
11097             FT_BOOLEAN, 8, TFS(&more_follow), 0x04, "More Segments Follow", HFILL }
11098         },
11099         { &hf_bacapp_SA,
11100           { "SA",           "bacapp.SA",
11101             FT_BOOLEAN, 8, TFS(&segmented_accept), 0x02, "Segmented Response accepted", HFILL }
11102         },
11103         { &hf_bacapp_max_adpu_size,
11104           { "Size of Maximum ADPU accepted",           "bacapp.max_adpu_size",
11105             FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, NULL, HFILL }
11106         },
11107         { &hf_bacapp_response_segments,
11108           { "Max Response Segments accepted",           "bacapp.response_segments",
11109             FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, NULL, HFILL }
11110         },
11111         { &hf_bacapp_objectType,
11112           { "Object Type",           "bacapp.objectType",
11113             FT_UINT32, BASE_DEC, VALS(BACnetObjectType), 0xffc00000, NULL, HFILL }
11114         },
11115         { &hf_bacapp_instanceNumber,
11116           { "Instance Number",           "bacapp.instance_number",
11117             FT_UINT32, BASE_DEC, NULL, 0x003fffff, NULL, HFILL }
11118         },
11119         { &hf_BACnetPropertyIdentifier,
11120           { "Property Identifier", "bacapp.property_identifier",
11121             FT_UINT32, BASE_DEC, VALS(BACnetPropertyIdentifier), 0, NULL, HFILL }
11122         },
11123         { &hf_BACnetVendorIdentifier,
11124           { "Vendor Identifier", "bacapp.vendor_identifier",
11125             FT_UINT16, BASE_DEC|BASE_EXT_STRING, &BACnetVendorIdentifiers_ext, 0, NULL, HFILL }
11126         },
11127         { &hf_BACnetRestartReason,
11128           { "Restart Reason", "bacapp.restart_reason",
11129             FT_UINT8, BASE_DEC, VALS(BACnetRestartReason), 0, NULL, HFILL }
11130         },
11131         { &hf_bacapp_invoke_id,
11132           { "Invoke ID",           "bacapp.invoke_id",
11133             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11134         },
11135         { &hf_bacapp_sequence_number,
11136           { "Sequence Number",           "bacapp.sequence_number",
11137             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11138         },
11139         { &hf_bacapp_window_size,
11140           { "Proposed Window Size",           "bacapp.window_size",
11141             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11142         },
11143         { &hf_bacapp_service,
11144           { "Service Choice",           "bacapp.confirmed_service",
11145             FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, NULL, HFILL }
11146         },
11147         { &hf_bacapp_uservice,
11148           { "Unconfirmed Service Choice",           "bacapp.unconfirmed_service",
11149             FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, NULL, HFILL }
11150         },
11151         { &hf_bacapp_NAK,
11152           { "NAK",           "bacapp.NAK",
11153             FT_BOOLEAN, 8, NULL, 0x02, "negative ACK", HFILL }
11154         },
11155         { &hf_bacapp_SRV,
11156           { "SRV",           "bacapp.SRV",
11157             FT_BOOLEAN, 8, NULL, 0x01, "Server", HFILL }
11158         },
11159         { &hf_Device_Instance_Range_Low_Limit,
11160           { "Device Instance Range Low Limit", "bacapp.who_is.low_limit",
11161             FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
11162         },
11163         { &hf_Device_Instance_Range_High_Limit,
11164           { "Device Instance Range High Limit", "bacapp.who_is.high_limit",
11165             FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
11166         },
11167         { &hf_BACnetRejectReason,
11168           { "Reject Reason",           "bacapp.reject_reason",
11169             FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, NULL, HFILL }
11170         },
11171         { &hf_BACnetAbortReason,
11172           { "Abort Reason",           "bacapp.abort_reason",
11173             FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, NULL, HFILL }
11174         },
11175         { &hf_BACnetApplicationTagNumber,
11176           { "Application Tag Number",
11177             "bacapp.application_tag_number",
11178             FT_UINT8, BASE_DEC, VALS(BACnetApplicationTagNumber), 0xF0,
11179             NULL, HFILL }
11180         },
11181         { &hf_BACnetContextTagNumber,
11182           { "Context Tag Number",
11183             "bacapp.context_tag_number",
11184             FT_UINT8, BASE_DEC, NULL, 0xF0,
11185             NULL, HFILL }
11186         },
11187         { &hf_BACnetExtendedTagNumber,
11188           { "Extended Tag Number",
11189             "bacapp.extended_tag_number",
11190             FT_UINT8, BASE_DEC, NULL, 0,
11191             NULL, HFILL }
11192         },
11193         { &hf_BACnetNamedTag,
11194           { "Named Tag",
11195             "bacapp.named_tag",
11196             FT_UINT8, BASE_DEC, VALS(BACnetTagNames), 0x07,
11197             NULL, HFILL }
11198         },
11199         { &hf_BACnetCharacterSet,
11200           { "String Character Set",
11201             "bacapp.string_character_set",
11202             FT_UINT8, BASE_DEC, VALS(BACnetCharacterSet), 0,
11203             NULL, HFILL }
11204         },
11205         { &hf_BACnetCodePage,
11206           { "Code Page",
11207             "bacapp.code_page",
11208             FT_UINT16, BASE_DEC, NULL, 0,
11209             NULL, HFILL }
11210         },
11211         { &hf_BACnetTagClass,
11212           { "Tag Class",           "bacapp.tag_class",
11213             FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, NULL, HFILL }
11214         },
11215         { &hf_bacapp_tag_lvt,
11216           { "Length Value Type",
11217             "bacapp.LVT",
11218             FT_UINT8, BASE_DEC, NULL, 0,
11219             NULL, HFILL }
11220         },
11221         { &hf_bacapp_tag_ProcessId,
11222           { "ProcessIdentifier",           "bacapp.processId",
11223             FT_UINT32, BASE_DEC, NULL, 0, "Process Identifier", HFILL }
11224         },
11225         { &hf_bacapp_tag_IPV4,
11226           { "IPV4",           "bacapp.IPV4",
11227             FT_IPv4, BASE_NONE, NULL, 0, "IP-Address", HFILL }
11228         },
11229         { &hf_bacapp_tag_IPV6,
11230           { "IPV6",           "bacapp.IPV6",
11231             FT_IPv6, BASE_NONE, NULL, 0, "IP-Address", HFILL }
11232         },
11233         { &hf_bacapp_tag_PORT,
11234           { "Port",           "bacapp.Port",
11235             FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
11236         },
11237         {&hf_msg_fragments,
11238          {"Message fragments", "bacapp.fragments",
11239           FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11240         {&hf_msg_fragment,
11241          {"Message fragment", "bacapp.fragment",
11242           FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11243         {&hf_msg_fragment_overlap,
11244          {"Message fragment overlap", "bacapp.fragment.overlap",
11245           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11246         {&hf_msg_fragment_overlap_conflicts,
11247          {"Message fragment overlapping with conflicting data",
11248           "bacapp.fragment.overlap.conflicts",
11249           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11250         {&hf_msg_fragment_multiple_tails,
11251          {"Message has multiple tail fragments",
11252           "bacapp.fragment.multiple_tails",
11253           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11254         {&hf_msg_fragment_too_long_fragment,
11255          {"Message fragment too long", "bacapp.fragment.too_long_fragment",
11256           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11257         {&hf_msg_fragment_error,
11258          {"Message defragmentation error", "bacapp.fragment.error",
11259           FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11260         {&hf_msg_fragment_count,
11261          {"Message fragment count", "bacapp.fragment.count",
11262           FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
11263         {&hf_msg_reassembled_in,
11264          {"Reassembled in", "bacapp.reassembled.in",
11265           FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11266         {&hf_msg_reassembled_length,
11267          {"Reassembled BACapp length", "bacapp.reassembled.length",
11268           FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }
11269     };
11270     static gint *ett[] = {
11271         &ett_bacapp,
11272         &ett_bacapp_control,
11273         &ett_bacapp_tag,
11274         &ett_bacapp_list,
11275         &ett_bacapp_value,
11276         &ett_msg_fragment,
11277         &ett_msg_fragments
11278
11279     };
11280
11281     static ei_register_info ei[] = {
11282         { &ei_bacapp_bad_length, { "bacapp.bad_length", PI_MALFORMED, PI_ERROR, "Wrong length indicated", EXPFILL }},
11283         { &ei_bacapp_bad_tag, { "bacapp.bad_tag", PI_MALFORMED, PI_ERROR, "Wrong tag found", EXPFILL }},
11284     };
11285
11286     expert_module_t* expert_bacapp;
11287
11288     proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
11289                                            "BACapp", "bacapp");
11290
11291     proto_register_field_array(proto_bacapp, hf, array_length(hf));
11292     proto_register_subtree_array(ett, array_length(ett));
11293     expert_bacapp = expert_register_protocol(proto_bacapp);
11294     expert_register_field_array(expert_bacapp, ei, array_length(ei));
11295     register_dissector("bacapp", dissect_bacapp, proto_bacapp);
11296     register_init_routine(&bacapp_init_routine);
11297
11298     bacapp_dissector_table = register_dissector_table("bacapp.vendor_identifier",
11299                                                       "BACapp Vendor Identifier",
11300                                                       FT_UINT8, BASE_HEX);
11301
11302     /* Register BACnet Statistic trees */
11303     register_bacapp_stat_trees();
11304     bacapp_tap = register_tap("bacapp"); /* BACnet statistics tap */
11305 }
11306
11307 /*
11308  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
11309  *
11310  * Local variables:
11311  * c-basic-offset: 4
11312  * tab-width: 8
11313  * indent-tabs-mode: nil
11314  * End:
11315  *
11316  * vi: set shiftwidth=4 tabstop=8 expandtab:
11317  * :indentSize=4:tabSize=8:noTabs=true:
11318  */