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