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