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