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