HTTPS (almost) everywhere.
[metze/wireshark/wip.git] / epan / dissectors / packet-ositp.c
1 /* packet-ositp.c
2  * Routines for ISO/OSI transport protocol (connection-oriented
3  * and connectionless) packet disassembly
4  *
5  * Laurent Deniel <laurent.deniel@free.fr>
6  * Ralf Schneider <Ralf.Schneider@t-online.de>
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * SPDX-License-Identifier: GPL-2.0-or-later
13  */
14
15 #include "config.h"
16
17 #include <epan/packet.h>
18 #include <epan/prefs.h>
19 #include <epan/reassemble.h>
20 #include <epan/conversation.h>
21 #include <epan/ipproto.h>
22 #include <epan/expert.h>
23 #include <epan/proto_data.h>
24
25 #include <wsutil/str_util.h>
26 #include "packet-frame.h"
27 #include "packet-osi.h"
28
29 void proto_register_cotp(void);
30 void proto_register_cltp(void);
31 void proto_reg_handoff_cotp(void);
32
33 /* protocols and fields */
34
35 static int  proto_clnp;
36
37 static int  proto_cotp         = -1;
38 static gint ett_cotp           = -1;
39 static gint ett_cotp_segments  = -1;
40 static gint ett_cotp_segment   = -1;
41
42 static int hf_cotp_li          = -1;
43 static int hf_cotp_type        = -1;
44 static int hf_cotp_srcref      = -1;
45 static int hf_cotp_destref     = -1;
46 static int hf_cotp_class       = -1;
47 static int hf_cotp_opts_extended_formats = -1;
48 static int hf_cotp_opts_no_explicit_flow_control = -1;
49 static int hf_cotp_tpdu_number = -1;
50 static int hf_cotp_tpdu_number_extended = -1;
51 static int hf_cotp_next_tpdu_number = -1;
52 static int hf_cotp_next_tpdu_number_extended = -1;
53 static int hf_cotp_eot          = -1;
54 static int hf_cotp_eot_extended = -1;
55 /* Generated from convert_proto_tree_add_text.pl */
56 static int hf_cotp_parameter_code = -1;
57 static int hf_cotp_parameter_length = -1;
58 static int hf_cotp_parameter_value = -1;
59 static int hf_cotp_atn_extended_checksum16 = -1;
60 static int hf_cotp_atn_extended_checksum32 = -1;
61 static int hf_cotp_atn_extended_checksum_status = -1;
62 static int hf_cotp_ack_time = -1;
63 static int hf_cotp_res_error_rate_target_value = -1;
64 static int hf_cotp_res_error_rate_min_accept = -1;
65 static int hf_cotp_res_error_rate_tdsu = -1;
66 static int hf_cotp_vp_priority = -1;
67 static int hf_cotp_transit_delay_targ_calling_called = -1;
68 static int hf_cotp_transit_delay_max_accept_calling_called = -1;
69 static int hf_cotp_transit_delay_targ_called_calling = -1;
70 static int hf_cotp_transit_delay_max_accept_called_calling = -1;
71 static int hf_cotp_max_throughput_targ_calling_called = -1;
72 static int hf_cotp_max_throughput_min_accept_calling_called = -1;
73 static int hf_cotp_max_throughput_targ_called_calling = -1;
74 static int hf_cotp_max_throughput_min_accept_called_calling = -1;
75 static int hf_cotp_avg_throughput_targ_calling_called = -1;
76 static int hf_cotp_avg_throughput_min_accept_calling_called = -1;
77 static int hf_cotp_avg_throughput_targ_called_calling = -1;
78 static int hf_cotp_avg_throughput_min_accept_called_calling = -1;
79 static int hf_cotp_sequence_number = -1;
80 static int hf_cotp_reassignment_time = -1;
81 static int hf_cotp_lower_window_edge = -1;
82 static int hf_cotp_credit = -1;
83 static int hf_cotp_tpdu_size = -1;
84 static int hf_cotp_checksum = -1;
85 static int hf_cotp_checksum_status = -1;
86 static int hf_cotp_vp_version_nr = -1;
87 static int hf_cotp_network_expedited_data = -1;
88 static int hf_cotp_vp_opt_sel_class1_use = -1;
89 static int hf_cotp_use_16_bit_checksum = -1;
90 static int hf_cotp_transport_expedited_data_transfer = -1;
91 static int hf_cotp_preferred_maximum_tpdu_size = -1;
92 static int hf_cotp_inactivity_timer = -1;
93 static int hf_cotp_cause = -1;
94 static int hf_cotp_segment_data = -1;
95 static int hf_cotp_credit_cdt = -1;
96 static int hf_cotp_reject_cause = -1;
97
98 static int hf_cotp_segments    = -1;
99 static int hf_cotp_segment     = -1;
100 static int hf_cotp_segment_overlap = -1;
101 static int hf_cotp_segment_overlap_conflict = -1;
102 static int hf_cotp_segment_multiple_tails = -1;
103 static int hf_cotp_segment_too_long_segment = -1;
104 static int hf_cotp_segment_error = -1;
105 static int hf_cotp_segment_count = -1;
106 static int hf_cotp_reassembled_in = -1;
107 static int hf_cotp_reassembled_length = -1;
108
109 static expert_field ei_cotp_disconnect_confirm = EI_INIT;
110 static expert_field ei_cotp_multiple_tpdus = EI_INIT;
111 static expert_field ei_cotp_reject = EI_INIT;
112 static expert_field ei_cotp_connection = EI_INIT;
113 static expert_field ei_cotp_disconnect_request = EI_INIT;
114 static expert_field ei_cotp_preferred_maximum_tpdu_size = EI_INIT;
115 static expert_field ei_cotp_atn_extended_checksum = EI_INIT;
116 static expert_field ei_cotp_checksum = EI_INIT;
117
118
119 static int  proto_cltp         = -1;
120 static gint ett_cltp           = -1;
121
122 static int hf_cltp_li = -1;
123 static int hf_cltp_type = -1;
124
125 static const fragment_items cotp_frag_items = {
126   &ett_cotp_segment,
127   &ett_cotp_segments,
128   &hf_cotp_segments,
129   &hf_cotp_segment,
130   &hf_cotp_segment_overlap,
131   &hf_cotp_segment_overlap_conflict,
132   &hf_cotp_segment_multiple_tails,
133   &hf_cotp_segment_too_long_segment,
134   &hf_cotp_segment_error,
135   &hf_cotp_segment_count,
136   &hf_cotp_reassembled_in,
137   &hf_cotp_reassembled_length,
138   /* Reassembled data field */
139   NULL,
140   "segments"
141 };
142
143 static dissector_handle_t rdp_cr_handle;
144 static dissector_handle_t rdp_cc_handle;
145 static dissector_handle_t ositp_handle;
146
147
148 /*
149  * ISO8073 OSI COTP definition
150  * See http://standards.iso.org/ittf/PubliclyAvailableStandards/index.html
151  * (or RFC905 for historic, and now-outdated information)
152  */
153
154 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
155
156 /* TPDU definition */
157
158 #define ED_TPDU             0x1 /* COTP */
159 #define EA_TPDU             0x2 /* COTP */
160 #define UD_TPDU             0x4 /* CLTP */
161 #define RJ_TPDU             0x5 /* COTP */
162 #define AK_TPDU             0x6 /* COTP */
163 #define ER_TPDU             0x7 /* COTP */
164 #define DR_TPDU             0x8 /* COTP */
165 #define DC_TPDU             0xC /* COTP */
166 #define CC_TPDU             0xD /* COTP */
167 #define CR_TPDU             0xE /* COTP */
168 #define DT_TPDU             0xF /* COTP */
169
170 static const value_string cotp_tpdu_type_abbrev_vals[] = {
171   { ED_TPDU, "ED Expedited Data" },
172   { EA_TPDU, "EA Expedited Data Acknowledgement" },
173   { RJ_TPDU, "RJ Reject" },
174   { AK_TPDU, "AK Data Acknowledgement" },
175   { ER_TPDU, "ER TPDU Error" },
176   { DR_TPDU, "DR Disconnect Request" },
177   { DC_TPDU, "DC Disconnect Confirm" },
178   { CC_TPDU, "CC Connect Confirm" },
179   { CR_TPDU, "CR Connect Request" },
180   { DT_TPDU, "DT Data" },
181   { 0,       NULL }
182 };
183
184 static const value_string cltp_tpdu_type_abbrev_vals[] = {
185   { UD_TPDU, "UD" },
186   { 0,       NULL }
187 };
188
189 #if 0
190 static const value_string class_option_vals[] = {
191   {0, "Class 0"},
192   {1, "Class 1"},
193   {2, "Class 2"},
194   {3, "Class 3"},
195   {4, "Class 4"},
196   {0, NULL}
197 };
198 #endif
199
200 /* field position */
201
202 #define P_LI                0
203 #define P_TPDU              1
204 #define P_CDT               1
205 #define P_DST_REF           2
206 #define P_SRC_REF           4
207 #define P_TPDU_NR_0_1       2
208 #define P_TPDU_NR_234       4
209 #define P_VAR_PART_NDT      5
210 #define P_VAR_PART_EDT      8
211 #define P_VAR_PART_DC       6
212 #define P_CDT_IN_AK         8
213 #define P_CDT_IN_RJ         8
214 #define P_REJECT_ER         4
215 #define P_REASON_IN_DR      6
216 #define P_CLASS_OPTION      6
217
218 /*
219  * TPDU length indicator values.
220  * Checksum parameter is 4 octets - 1 octet of parameter code, 1 octet
221  * of parameter length, 2 octets of checksum.
222  */
223
224 #define LI_NORMAL_DT_CLASS_01           2
225 #define LI_NORMAL_DT_WITHOUT_CHECKSUM   4
226 #define LI_NORMAL_DT_WITH_CHECKSUM      (LI_NORMAL_DT_WITHOUT_CHECKSUM+4)
227 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
228 #define LI_EXTENDED_DT_WITH_CHECKSUM    (LI_EXTENDED_DT_WITHOUT_CHECKSUM+4)
229 #define LI_NORMAL_EA_WITHOUT_CHECKSUM   4
230 #define LI_NORMAL_EA_WITH_CHECKSUM      (LI_NORMAL_EA_WITHOUT_CHECKSUM+4)
231 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
232 #define LI_EXTENDED_EA_WITH_CHECKSUM    (LI_EXTENDED_EA_WITHOUT_CHECKSUM+4)
233 #define LI_NORMAL_RJ                    4
234 #define LI_EXTENDED_RJ                  9
235 #define LI_MIN_DR                       6
236 #define LI_MAX_DC                       9
237 #define LI_MAX_AK                       27
238 #define LI_MAX_EA                       11
239 #define LI_MAX_ER                       8
240 /* XXX - can we always decide this based on whether the length
241    indicator is odd or not?  What if the variable part has an odd
242    number of octets? */
243 #define is_LI_NORMAL_AK(p)               ((p & 0x01) == 0)
244
245 /*
246  * Modified TPDU length indicator values due to ATN 4-octet extended
247  * checksum.
248  * Checksum parameter is 6 octets - 1 octet of parameter code, 1 octet
249  * of parameter length, 4 octets of checksum.  That adds 2 octets to
250  * the lengths with a 2-octet checksum.
251  */
252 #define LI_ATN_NORMAL_DT_WITH_CHECKSUM       (LI_NORMAL_DT_WITH_CHECKSUM+2)
253 #define LI_ATN_EXTENDED_DT_WITH_CHECKSUM     (LI_EXTENDED_DT_WITH_CHECKSUM+2)
254 #define LI_ATN_NORMAL_EA_WITH_CHECKSUM       (LI_NORMAL_EA_WITH_CHECKSUM+2)
255 #define LI_ATN_EXTENDED_EA_WITH_CHECKSUM     (LI_EXTENDED_EA_WITH_CHECKSUM+2)
256 #define LI_ATN_NORMAL_RJ                     (LI_NORMAL_RJ+2)
257 #define LI_ATN_EXTENDED_RJ                   (LI_EXTENDED_RJ+2)
258 #define LI_ATN_MAX_DC                        (LI_MAX_DC+2)
259 #define LI_ATN_MAX_AK                        (LI_MAX_AK+2+1) /* +1 for padding? */
260 #define LI_ATN_MAX_EA                        (LI_MAX_EA+2)
261 #define LI_ATN_MAX_ER                        (LI_MAX_ER+2)
262
263 /* variant part */
264
265 #define VP_ACK_TIME             0x85
266 #define VP_RES_ERROR            0x86
267 #define VP_PRIORITY             0x87
268 #define VP_TRANSIT_DEL          0x88
269 #define VP_THROUGHPUT           0x89
270 #define VP_SEQ_NR               0x8A        /* in AK */
271 #define VP_REASSIGNMENT         0x8B
272 #define VP_FLOW_CNTL            0x8C        /* in AK */
273 #define VP_TPDU_SIZE            0xC0
274 #define VP_SRC_TSAP             0xC1        /* in CR/CC */
275 #define VP_DST_TSAP             0xC2
276 #define VP_CHECKSUM             0xC3
277 #define VP_VERSION_NR           0xC4
278 #define VP_PROTECTION           0xC5
279 #define VP_OPT_SEL              0xC6
280 #define VP_PROTO_CLASS          0xC7
281 #define VP_CLEARING_INFO        0xE0        /* in DR */
282 #define VP_PREF_MAX_TPDU_SIZE   0xF0
283 #define VP_INACTIVITY_TIMER     0xF2
284
285 /* ATN */
286 /* Parameter codes with bits 7 and 8 are explicitly not */
287 /* assigned by ISO/IEC 8073, nor is their use precluded. */
288 /* Parameter codes for ATN defined in ICAO doc 9507 Ed3 SV 5 section 5.5.2.4.3.1 */
289 #define VP_ATN_EC_32            0x08        /* 4 octet ATN Extended Transport Checksum parameter */
290 #define VP_ATN_EC_16            0x09        /* 2 octet ATN Extended Transport Checksum parameter */
291 /* ATN end */
292
293 static const value_string tp_vpart_type_vals[] = {
294   { VP_ATN_EC_16,           "ATN extended checksum - 16 bit" },
295   { VP_ATN_EC_32,           "ATN extended checksum - 32 bit" },
296   { VP_ACK_TIME,            "ack time" },
297   { VP_RES_ERROR,           "res error" },
298   { VP_PRIORITY,            "priority" },
299   { VP_TRANSIT_DEL,         "transit delay" },
300   { VP_THROUGHPUT,          "throughput" },
301   { VP_SEQ_NR,              "seq number" },
302   { VP_REASSIGNMENT,        "reassignment" },
303   { VP_FLOW_CNTL,           "flow control" },
304   { VP_TPDU_SIZE,           "tpdu-size" },
305   { VP_SRC_TSAP,            "src-tsap" },
306   { VP_DST_TSAP,            "dst-tsap" },
307   { VP_CHECKSUM,            "checksum" },
308   { VP_VERSION_NR,          "version" },
309   { VP_PROTECTION,          "protection" },
310   { VP_OPT_SEL,             "options" },
311   { VP_PROTO_CLASS,         "proto class" },
312   { VP_CLEARING_INFO,       "additional connection clearing info" },
313   { VP_PREF_MAX_TPDU_SIZE,  "preferred max TPDU size" },
314   { VP_INACTIVITY_TIMER,    "inactivity timer" },
315   { 0,                      NULL }
316 };
317
318 static int hf_cotp_vp_src_tsap = -1;
319 static int hf_cotp_vp_dst_tsap = -1;
320 static int hf_cotp_vp_src_tsap_bytes = -1;
321 static int hf_cotp_vp_dst_tsap_bytes = -1;
322
323 /* global variables */
324
325 /* List of dissectors to call for the variable part of CR PDUs. */
326 static heur_dissector_list_t cotp_cr_heur_subdissector_list;
327 /* List of dissectors to call for the variable part of CC PDUs. */
328 static heur_dissector_list_t cotp_cc_heur_subdissector_list;
329 /* List of dissectors to call for COTP packets put atop the Inactive
330    Subset of CLNP. */
331 static heur_dissector_list_t cotp_is_heur_subdissector_list;
332 /* List of dissectors to call for COTP packets put atop CLNP */
333 static heur_dissector_list_t cotp_heur_subdissector_list;
334 /* List of dissectors to call for CLTP packets put atop CLNP */
335 static heur_dissector_list_t cltp_heur_subdissector_list;
336
337 /*
338  * Reassembly of COTP.
339  */
340 static reassembly_table cotp_reassembly_table;
341 static guint16    cotp_dst_ref = 0;
342 static gboolean   cotp_frame_reset = FALSE;
343 static gboolean   cotp_last_fragment = FALSE;
344
345 #define TSAP_DISPLAY_AUTO   0
346 #define TSAP_DISPLAY_STRING 1
347 #define TSAP_DISPLAY_BYTES  2
348
349 /* options */
350 static gboolean cotp_reassemble = TRUE;
351 static gint32   tsap_display = TSAP_DISPLAY_AUTO;
352 static gboolean cotp_decode_atn = FALSE;
353
354 static const enum_val_t tsap_display_options[] = {
355   {"auto", "As strings if printable", TSAP_DISPLAY_AUTO},
356   {"string", "As strings", TSAP_DISPLAY_STRING},
357   {"bytes", "As bytes", TSAP_DISPLAY_BYTES},
358   {NULL, NULL, -1}
359 };
360
361 /* function definitions */
362
363 #define MAX_TSAP_LEN    32
364
365 static void cotp_frame_end(void)
366 {
367   if (!cotp_last_fragment) {
368     /* Last COTP in frame is not fragmented.
369      * No need for incrementing the dst_ref, so we decrement it here.
370      */
371     cotp_dst_ref--;
372   }
373   cotp_frame_reset = TRUE;
374 }
375
376 static gchar *print_tsap(tvbuff_t *tvb, int offset, int length)
377 {
378   const guchar *tsap = tvb_get_ptr(tvb, offset, length);
379   gchar    *cur;
380   gboolean  allprintable;
381   gint      idx = 0, returned_length;
382
383   cur=(gchar *)wmem_alloc(wmem_packet_scope(), MAX_TSAP_LEN * 2 + 3);
384   cur[0] = '\0';
385   if (length <= 0 || length > MAX_TSAP_LEN)
386     g_snprintf(cur, MAX_TSAP_LEN * 2 + 3, "<unsupported TSAP length>");
387   else {
388     allprintable = tvb_ascii_isprint(tvb, offset, length);
389     if (!allprintable) {
390       returned_length = g_snprintf(cur, MAX_TSAP_LEN * 2 + 3, "0x");
391       idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - 1);
392     }
393     while (length != 0) {
394       if (allprintable) {
395         returned_length = g_snprintf(&cur[idx], MAX_TSAP_LEN * 2 + 3 - idx,
396                                      "%c", *tsap ++);
397         idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - idx - 1);
398       } else {
399         returned_length = g_snprintf(&cur[idx], MAX_TSAP_LEN * 2 + 3 - idx,
400                                      "%02x", *tsap ++);
401         idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - idx - 1);
402       }
403       length --;
404     }
405   }
406   return cur;
407
408 } /* print_tsap */
409
410 static const true_false_string tfs_vp_opt_sel_class1_use = { "Receipt confirmation", "explicit AK variant" };
411
412 static gboolean ositp_decode_var_part(tvbuff_t *tvb, int offset, int vp_length,
413                                       int class_option, int tpdu_len,
414                                       packet_info *pinfo, proto_tree *tree)
415 {
416   guint8          code, length;
417   guint8          c1;
418   guint16         s;
419   guint32         offset_iso8073_checksum = 0;
420   gint32          i                       = 0;
421   guint8          tmp_code                = 0;
422   guint           tmp_len                 = 0;
423   guint32         pref_max_tpdu_size;
424   proto_item     *hidden_item;
425
426   while (vp_length != 0) {
427     code = tvb_get_guint8(tvb, offset);
428     proto_tree_add_item(tree, hf_cotp_parameter_code, tvb, offset, 1, ENC_NA);
429     offset += 1;
430     vp_length -= 1;
431
432     if (vp_length == 0)
433       break;
434     length = tvb_get_guint8(tvb, offset);
435     proto_tree_add_item(tree, hf_cotp_parameter_length, tvb, offset, 1, ENC_NA);
436     offset += 1;
437     vp_length -= 1;
438
439     switch (code) {
440
441     case VP_ATN_EC_16 : /* ATN */
442       if (cotp_decode_atn) {
443         guint16 sum;
444         /* if an alternate OSI checksum is present in the currently unprocessed
445          * VP section to the checksum algorithm has to know.
446          * this may be the case for backward compatible CR TPDU */
447         if (!offset_iso8073_checksum) {
448           /* search following parameters in VP part for ISO checksum */
449           for (i = offset + length; i < vp_length;) {
450             tmp_code = tvb_get_guint8(tvb, i++);
451             tmp_len = tvb_get_guint8(tvb, i++);
452             if (tmp_code == VP_CHECKSUM) {
453               offset_iso8073_checksum = i; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
454               break;
455             }
456             i += tmp_len;
457           }
458         }
459         sum = check_atn_ec_16(tvb, tpdu_len , offset,
460                                       offset_iso8073_checksum,
461                                       pinfo->dst.len, (const guint8 *)pinfo->dst.data,
462                                       pinfo->src.len, (const guint8 *)pinfo->src.data);
463         proto_tree_add_checksum(tree, tvb, offset, hf_cotp_atn_extended_checksum16, hf_cotp_atn_extended_checksum_status, &ei_cotp_atn_extended_checksum,
464                                 pinfo, sum, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_ZERO);
465       } else {
466         proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
467       }
468       offset += length;
469       vp_length -= length;
470       break;
471
472     case VP_ATN_EC_32 : /* ATN */
473       if (cotp_decode_atn) {
474         guint32 sum;
475         /* if an alternate OSI checksum is present in the currently unprocessed
476          * VP section the checksum algorithm has to know.
477          * this may be the case for backward compatible CR TPDU */
478         if (!offset_iso8073_checksum) {
479           /* search following parameters in VP part for ISO checksum */
480           for (i = offset + length; i < vp_length;) {
481             tmp_code = tvb_get_guint8(tvb, i++);
482             tmp_len = tvb_get_guint8(tvb, i++);
483             if (tmp_code == VP_CHECKSUM) {
484               offset_iso8073_checksum = i; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
485               break;
486             }
487             i += tmp_len;
488           }
489         }
490         sum = check_atn_ec_32(tvb, tpdu_len , offset,
491                                       offset_iso8073_checksum,
492                                       pinfo->dst.len, (const guint8 *)pinfo->dst.data,
493                                       pinfo->src.len, (const guint8 *)pinfo->src.data);
494         proto_tree_add_checksum(tree, tvb, offset, hf_cotp_atn_extended_checksum32, hf_cotp_atn_extended_checksum_status, &ei_cotp_atn_extended_checksum,
495                                 pinfo, sum, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_ZERO);
496       } else {
497         proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
498       }
499       offset += length;
500       vp_length -= length;
501       break;
502
503     case VP_ACK_TIME:
504       proto_tree_add_item(tree, hf_cotp_ack_time, tvb, offset, length, ENC_BIG_ENDIAN);
505       offset += length;
506       vp_length -= length;
507       break;
508
509     case VP_RES_ERROR:
510       s = tvb_get_guint8(tvb, offset);
511       proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_target_value, tvb, offset, 1, s, "10^%u", s);
512       offset += 1;
513       vp_length -= 1;
514
515       s = tvb_get_guint8(tvb, offset);
516       proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_min_accept, tvb, offset, 1, s, "10^%u", s);
517       offset += 1;
518       vp_length -= 1;
519
520       s = tvb_get_guint8(tvb, offset);
521       proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_tdsu, tvb, offset, 1, s, "2^%u", s);
522       offset += 1;
523       vp_length -= 1;
524       break;
525
526     case VP_PRIORITY:
527       proto_tree_add_item(tree, hf_cotp_vp_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
528       offset += length;
529       vp_length -= length;
530       break;
531
532     case VP_TRANSIT_DEL:
533       proto_tree_add_item(tree, hf_cotp_transit_delay_targ_calling_called, tvb, offset, 2, ENC_BIG_ENDIAN);
534       offset += 2;
535       vp_length -= 2;
536
537       proto_tree_add_item(tree, hf_cotp_transit_delay_max_accept_calling_called, tvb, offset, 2, ENC_BIG_ENDIAN);
538       offset += 2;
539       vp_length -= 2;
540
541       proto_tree_add_item(tree, hf_cotp_transit_delay_targ_called_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
542       offset += 2;
543       vp_length -= 2;
544
545       proto_tree_add_item(tree, hf_cotp_transit_delay_max_accept_called_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
546       offset += 2;
547       vp_length -= 2;
548       break;
549
550     case VP_THROUGHPUT:
551       proto_tree_add_item(tree, hf_cotp_max_throughput_targ_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
552       offset += 3;
553       length -= 3;
554       vp_length -= 3;
555
556       proto_tree_add_item(tree, hf_cotp_max_throughput_min_accept_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
557       offset += 3;
558       length -= 3;
559       vp_length -= 3;
560
561       proto_tree_add_item(tree, hf_cotp_max_throughput_targ_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
562       offset += 3;
563       length -= 3;
564       vp_length -= 3;
565
566       proto_tree_add_item(tree, hf_cotp_max_throughput_min_accept_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
567       offset += 3;
568       length -= 3;
569       vp_length -= 3;
570
571       if (length != 0) {    /* XXX - should be 0 or 12 */
572         proto_tree_add_item(tree, hf_cotp_avg_throughput_targ_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
573         offset += 3;
574         vp_length -= 3;
575
576         proto_tree_add_item(tree, hf_cotp_avg_throughput_min_accept_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
577         offset += 3;
578         vp_length -= 3;
579
580         proto_tree_add_item(tree, hf_cotp_avg_throughput_targ_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
581         offset += 3;
582         vp_length -= 3;
583
584         proto_tree_add_item(tree, hf_cotp_avg_throughput_min_accept_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
585         offset += 3;
586         vp_length -= 3;
587       }
588       break;
589
590     case VP_SEQ_NR:
591       proto_tree_add_item(tree, hf_cotp_sequence_number, tvb, offset, 2, ENC_BIG_ENDIAN);
592       offset += length;
593       vp_length -= length;
594       break;
595
596     case VP_REASSIGNMENT:
597       proto_tree_add_item(tree, hf_cotp_reassignment_time, tvb, offset, 2, ENC_BIG_ENDIAN);
598       offset += length;
599       vp_length -= length;
600       break;
601
602     case VP_FLOW_CNTL:
603       proto_tree_add_item(tree, hf_cotp_lower_window_edge, tvb, offset, 4, ENC_BIG_ENDIAN);
604       offset += 4;
605       vp_length -= 4;
606
607       proto_tree_add_item(tree, hf_cotp_sequence_number, tvb, offset, 2, ENC_BIG_ENDIAN);
608       offset += 2;
609       vp_length -= 2;
610
611       proto_tree_add_item(tree, hf_cotp_credit, tvb, offset, 2, ENC_BIG_ENDIAN);
612       offset += 2;
613       vp_length -= 2;
614
615       break;
616
617     case VP_TPDU_SIZE:
618       c1 = tvb_get_guint8(tvb, offset) & 0x0F;
619       proto_tree_add_uint(tree, hf_cotp_tpdu_size, tvb, offset, 1, 1 << c1);
620       offset += length;
621       vp_length -= length;
622       break;
623
624     case VP_SRC_TSAP:
625       /* if our preference is set to STRING or the TSAP is not printable,
626        * add as bytes and hidden as string; otherwise vice-versa */
627       if (tsap_display==TSAP_DISPLAY_STRING ||
628           (tsap_display==TSAP_DISPLAY_AUTO &&
629             tvb_ascii_isprint(tvb, offset, length))) {
630         proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb, offset, length,
631                               print_tsap(tvb, offset, length));
632         hidden_item = proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb,
633                                           offset, length, ENC_NA);
634         proto_item_set_hidden(hidden_item);
635       } else {
636         hidden_item = proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb,
637                                             offset, length,
638                                             print_tsap(tvb, offset, length));
639         proto_item_set_hidden(hidden_item);
640         proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb, offset,
641                             length, ENC_NA);
642       }
643       offset += length;
644       vp_length -= length;
645       break;
646
647     case VP_DST_TSAP:
648       /* if our preference is set to STRING or the TSAP is not printable,
649        * add as bytes and hidden as string; otherwise vice-versa */
650       if (tsap_display==TSAP_DISPLAY_STRING ||
651           (tsap_display==TSAP_DISPLAY_AUTO &&
652             tvb_ascii_isprint(tvb, offset, length))) {
653         proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb, offset, length,
654                               print_tsap(tvb, offset, length));
655         hidden_item = proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb,
656                                           offset, length, ENC_NA);
657         proto_item_set_hidden(hidden_item);
658       } else {
659         hidden_item = proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb,
660                                             offset, length,
661                                             print_tsap(tvb, offset, length));
662         proto_item_set_hidden(hidden_item);
663         proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb, offset,
664                             length, ENC_NA);
665       }
666       offset += length;
667       vp_length -= length;
668       break;
669
670     case VP_CHECKSUM:
671       offset_iso8073_checksum = offset; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
672
673       if (tvb_get_ntohs(tvb, offset) == 0) {
674         /* No checksum present */
675         proto_tree_add_checksum(tree, tvb, offset, hf_cotp_checksum, hf_cotp_checksum_status, &ei_cotp_checksum, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NOT_PRESENT);
676       } else {
677         guint32 calc_c0 = 0, calc_c1 = 0;
678
679         if (osi_calc_checksum(tvb, 0, length, &calc_c0, &calc_c1)) {
680             /* Successfully processed checksum, verify it */
681             proto_tree_add_checksum(tree, tvb, offset, hf_cotp_checksum, hf_cotp_checksum_status, &ei_cotp_checksum, pinfo, calc_c0 | calc_c1, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_ZERO);
682         } else {
683             proto_tree_add_checksum(tree, tvb, offset, hf_cotp_checksum, hf_cotp_checksum_status, &ei_cotp_checksum, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
684         }
685       }
686
687       offset += length;
688       vp_length -= length;
689       break;
690
691     case VP_VERSION_NR:
692       proto_tree_add_item(tree, hf_cotp_vp_version_nr, tvb, offset, 1, ENC_NA);
693       offset += length;
694       vp_length -= length;
695       break;
696
697     case VP_OPT_SEL:
698       switch (class_option) {
699
700       case 1:
701         proto_tree_add_item(tree, hf_cotp_network_expedited_data, tvb, offset, 1, ENC_NA);
702
703         proto_tree_add_item(tree, hf_cotp_vp_opt_sel_class1_use, tvb, offset, 1, ENC_NA);
704         break;
705
706       case 4:
707         proto_tree_add_item(tree, hf_cotp_use_16_bit_checksum, tvb, offset, 1, ENC_NA);
708         break;
709       }
710
711       proto_tree_add_item(tree, hf_cotp_transport_expedited_data_transfer, tvb, offset, 1, ENC_NA);
712       offset += length;
713       vp_length -= length;
714       break;
715
716     case VP_PREF_MAX_TPDU_SIZE:
717       switch (length) {
718
719       case 1:
720         pref_max_tpdu_size = tvb_get_guint8(tvb, offset);
721         break;
722
723       case 2:
724         pref_max_tpdu_size = tvb_get_ntohs(tvb, offset);
725         break;
726
727       case 3:
728         pref_max_tpdu_size = tvb_get_ntoh24(tvb, offset);
729         break;
730
731       case 4:
732         pref_max_tpdu_size = tvb_get_ntohl(tvb, offset);
733         break;
734
735       default:
736         proto_tree_add_expert_format(tree, pinfo, &ei_cotp_preferred_maximum_tpdu_size, tvb, offset, length,
737                             "Preferred maximum TPDU size: bogus length %u (not 1, 2, 3, or 4)", length);
738         return FALSE;
739       }
740       proto_tree_add_uint(tree, hf_cotp_preferred_maximum_tpdu_size, tvb, offset, length, pref_max_tpdu_size*128);
741       offset += length;
742       vp_length -= length;
743       break;
744
745     case VP_INACTIVITY_TIMER:
746       proto_tree_add_item(tree, hf_cotp_inactivity_timer, tvb, offset, length, ENC_BIG_ENDIAN);
747       offset += length;
748       vp_length -= length;
749       break;
750
751     case VP_PROTECTION:             /* user-defined */
752     case VP_PROTO_CLASS:            /* todo */
753     case VP_CLEARING_INFO:          /* user-defined */
754     default:                        /* unknown, no decoding */
755       proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
756       offset += length;
757       vp_length -= length;
758       break;
759     }
760   } /* while */
761
762   return TRUE;
763 }
764
765 static const value_string cotp_cause_vals[] = {
766   { 0, "Reason not specified" },
767   { 1, "Congestion at TSAP" },
768   { 2, "Session entity not attached to TSAP" },
769   { 3, "Address unknown" },
770   { 128+0, "Normal Disconnect" },
771   { 128+1, "Remote transport entity congestion" },
772   { 128+2, "Connection negotiation failed" },
773   { 128+3, "Duplicate source reference" },
774   { 128+4, "Mismatched references" },
775   { 128+5, "Protocol error" },
776   { 128+7, "Reference overflow" },
777   { 128+8, "Connection request refused" },
778   { 128+10, "Header or parameter length invalid" },
779   { 0,       NULL }
780 };
781
782 static int ositp_decode_DR(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
783                            packet_info *pinfo, proto_tree *tree)
784 {
785   proto_tree *cotp_tree = NULL;
786   proto_item *ti        = NULL;
787   guint16     dst_ref, src_ref;
788   guchar      reason;
789   guint       tpdu_len;
790
791   /* ATN TPDU's tend to be larger than normal OSI,
792    * so nothing to do with respect to LI checks */
793   if (li < LI_MIN_DR)
794     return -1;
795
796   /* DR TPDUs can have user data, so they run to the end of the containing PDU */
797   tpdu_len = tvb_reported_length_remaining(tvb, offset);
798
799   dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
800
801   src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
802
803   reason  = tvb_get_guint8(tvb, offset + P_REASON_IN_DR);
804
805   pinfo->clnp_dstref = dst_ref;
806   pinfo->clnp_srcref = src_ref;
807
808   /* the settings of the TCP srcport and destport are currently disabled,
809    * for the following reasons:
810    * a) only used for ISO conversation handling (which currently doesn't work)
811    * b) will prevent "ISO on TCP" (RFC1006) packets from using
812    *    "follow TCP stream" correctly
813    *
814    * A future conversation handling might be able to handle different kinds of
815    * conversations (TCP, ISO, TCP on TCP, ...), but in that case this has to be
816    * fixed in any case.
817    */
818   /*pinfo->srcport = src_ref;*/
819   /*pinfo->destport = dst_ref;*/
820   if (try_val_to_str(reason, cotp_cause_vals) == NULL)
821       return -1;
822
823   col_append_fstr(pinfo->cinfo, COL_INFO,
824                   "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref, dst_ref);
825
826   if (tree) {
827     ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
828     cotp_tree = proto_item_add_subtree(ti, ett_cotp);
829     proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
830     proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset +  1, 1, tpdu);
831     proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset +  2, 2,
832                         dst_ref);
833     proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset +  4, 2,
834                         src_ref);
835     proto_tree_add_item(cotp_tree, hf_cotp_cause, tvb, offset + 6, 1, ENC_NA);
836   }
837   offset += 7;
838   li -= 6;
839
840   if (tree)
841     ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
842   offset += li;
843
844   expert_add_info_format(pinfo, ti, &ei_cotp_disconnect_request, "Disconnect Request(DR): 0x%x -> 0x%x", src_ref, dst_ref);
845
846   /* User data */
847   call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
848   offset += tvb_captured_length_remaining(tvb, offset);
849      /* we dissected all of the containing PDU */
850
851   return offset;
852
853 } /* ositp_decode_DR */
854
855 static int ositp_decode_DT(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
856                            packet_info *pinfo, proto_tree *tree,
857                            gboolean uses_inactive_subset,
858                            gboolean *subdissector_found)
859 {
860   proto_tree        *cotp_tree       = NULL;
861   proto_item        *ti;
862   gboolean           is_extended;
863   gboolean           is_class_234;
864   guint32            dst_ref;
865   guint32           *prev_dst_ref;
866   guint              tpdu_nr;
867   gboolean           fragment        = FALSE;
868   guint32            fragment_length = 0;
869   tvbuff_t          *next_tvb;
870   fragment_head     *fd_head;
871   conversation_t    *conv;
872   guint              tpdu_len;
873   heur_dtbl_entry_t *hdtbl_entry;
874
875   /* DT TPDUs have user data, so they run to the end of the containing PDU */
876   tpdu_len = tvb_reported_length_remaining(tvb, offset);
877
878   /* The fixed part is 2 octets long, not including the length indicator,
879      for classes 0 and 1; it is at least 4 octets long, not including
880      the length indicator, for classes 2, 3, and 4. */
881   is_class_234 = (li > LI_NORMAL_DT_CLASS_01);
882
883   /* note: in the ATN the user is up to chose between 3 different checksums:
884    *       standard OSI, 2 or 4 octet extended checksum.
885    * The differences for DT are that the TPDU headers may be enlarged by 2
886    * octets and that checksum related option codes and option lengths are
887    * different.  To not mess up the original OSI dissector LI checking was
888    * implemented separately. */
889   if (!cotp_decode_atn) { /* non ATN, plain OSI*/
890     /* VP_CHECKSUM is the only parameter allowed in the variable part.
891      * (This means we may misdissect this if the packet is bad and
892      * contains other parameters.).
893
894      * XXX - not true; ISO/IEC 8073:1997 (E) says that "if the use of
895      * non-blocking expedited data transfer service is negotiated (class
896      * 4 only), the variable part shall contain the ED-TPDU-NR for the
897      * first DT-TPDU created from a T-DATA request subsequent to the
898      * T-EXPEDITED DATA request". */
899     switch (li) {
900
901       case LI_NORMAL_DT_WITH_CHECKSUM      :
902         if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
903           return -1;
904         /* FALLTHROUGH */
905
906       case LI_NORMAL_DT_WITHOUT_CHECKSUM   :
907         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
908         if (tpdu_nr & 0x80)
909           tpdu_nr = tpdu_nr & 0x7F;
910         else
911           fragment = TRUE;
912         is_extended = FALSE;
913         dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
914         break;
915
916       case LI_EXTENDED_DT_WITH_CHECKSUM    :
917         if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
918           return -1;
919         /* FALLTHROUGH */
920
921       case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
922         tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
923         if (tpdu_nr & 0x80000000)
924           tpdu_nr = tpdu_nr & 0x7FFFFFFF;
925         else
926           fragment = TRUE;
927         is_extended = TRUE;
928         dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
929         break;
930
931       case LI_NORMAL_DT_CLASS_01           :
932         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_0_1);
933         if (tpdu_nr & 0x80)
934           tpdu_nr = tpdu_nr & 0x7F;
935         else
936           fragment = TRUE;
937         is_extended = FALSE;
938         prev_dst_ref = (guint32 *)p_get_proto_data(wmem_file_scope(), pinfo, proto_clnp, 0);
939         if (!prev_dst_ref) {
940           /* First COTP in frame - save previous dst_ref as offset */
941           prev_dst_ref = wmem_new(wmem_file_scope(), guint32);
942           *prev_dst_ref = cotp_dst_ref;
943           p_add_proto_data(wmem_file_scope(), pinfo, proto_clnp, 0, prev_dst_ref);
944         } else if (cotp_frame_reset) {
945           cotp_dst_ref = *prev_dst_ref;
946         }
947         cotp_frame_reset = FALSE;
948         cotp_last_fragment = fragment;
949         dst_ref = cotp_dst_ref;
950         conv = find_conversation_pinfo(pinfo, 0);
951         if (conv) {
952           /* Found a conversation, also use index for the generated dst_ref */
953           dst_ref += (conv->conv_index << 16);
954         }
955         if (!fragment) {
956           cotp_dst_ref++;
957           register_frame_end_routine(pinfo, cotp_frame_end);
958         }
959         break;
960
961       default : /* bad TPDU */
962         return -1;
963     } /* li */
964   } else {
965     /* check ATN class4 TPDU's here */
966
967     /* check packet length indicators of DaTa(DT) TPDU
968      * note: use of checksum depends on the selected RER
969      *       (high:non-use medium:16-bit OSI/16-bit ext.ATN low:32-bit ext. ATN)
970      *
971      * note: sole use of TP4 class in the ATN
972      * note: normal/extended TPDU numbering is negociable */
973     switch (li) {
974
975       /* normal DT with 2 octets of OSI or of ATN Extended Checksum */
976       case LI_NORMAL_DT_WITH_CHECKSUM      :
977         if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM &&
978             tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16)
979           return -1;
980         /* FALLTHROUGH */
981
982       case LI_NORMAL_DT_WITHOUT_CHECKSUM   :
983         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
984         if (tpdu_nr & 0x80)
985           tpdu_nr = tpdu_nr & 0x7F;
986         else
987           fragment = TRUE;
988         is_extended = FALSE;
989         dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
990         break;
991
992       /* extended DT with 2 octets of OSI or of ATN Extended Checksum */
993       case LI_EXTENDED_DT_WITH_CHECKSUM    :
994         if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM &&
995             tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16)
996           return -1;
997         /* FALLTHROUGH */
998
999       case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1000         tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1001         if (tpdu_nr & 0x80000000)
1002           tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1003         else
1004           fragment = TRUE;
1005         is_extended = TRUE;
1006         dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1007         break;
1008
1009       /* normal DT with ATN Extended Checksum (4 octets)*/
1010       case LI_ATN_NORMAL_DT_WITH_CHECKSUM      :
1011         if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32)
1012           return -1;
1013
1014         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1015
1016         if (tpdu_nr & 0x80)
1017           tpdu_nr = tpdu_nr & 0x7F;
1018         else
1019           fragment = TRUE;
1020         is_extended = FALSE;
1021         dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1022         break;
1023
1024       /* extended DT with 4 octets ATN Extended Checksum  */
1025       case LI_ATN_EXTENDED_DT_WITH_CHECKSUM:
1026         if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32)
1027           return -1;
1028
1029         tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1030         if (tpdu_nr & 0x80000000)
1031           tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1032         else
1033           fragment = TRUE;
1034         is_extended = TRUE;
1035         dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1036         break;
1037
1038       default : /* bad TPDU */
1039         return -1;
1040     } /* li */
1041   } /* cotp_decode_atn */
1042
1043   pinfo->clnp_dstref = dst_ref;
1044
1045   pinfo->fragmented = fragment;
1046   if (is_class_234) {
1047       col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x",
1048                       tpdu_nr, dst_ref);
1049     } else {
1050       col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u)", tpdu_nr);
1051     }
1052
1053   if (tree) {
1054     ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1055     cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1056     proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1057   }
1058   offset += 1;
1059
1060   if (tree) {
1061     proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1062   }
1063   offset += 1;
1064   li -= 1;
1065
1066   if (is_class_234) {
1067     if (tree)
1068       proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1069     offset += 2;
1070     li -= 2;
1071   } else if (tree) {
1072     ti = proto_tree_add_uint (cotp_tree, hf_cotp_destref, tvb, offset, 0,
1073                               dst_ref);
1074     proto_item_set_generated (ti);
1075   }
1076
1077   if (is_extended) {
1078     if (tree) {
1079       proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb, offset,
1080                           4, tpdu_nr);
1081       proto_tree_add_item(cotp_tree, hf_cotp_eot_extended, tvb, offset, 4,
1082                           ENC_BIG_ENDIAN);
1083     }
1084     offset += 4;
1085     li -= 4;
1086   } else {
1087     if (tree) {
1088       proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
1089                           tpdu_nr);
1090       proto_tree_add_item(cotp_tree, hf_cotp_eot, tvb, offset, 1,
1091                           ENC_BIG_ENDIAN);
1092     }
1093     offset += 1;
1094     li -= 1;
1095   }
1096
1097   if (tree)
1098     ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1099   offset += li;
1100
1101   next_tvb = tvb_new_subset_remaining(tvb, offset);
1102   fragment_length = tvb_captured_length(next_tvb);
1103   if (fragment) {
1104     col_append_fstr(pinfo->cinfo, COL_INFO, " [COTP fragment, %u byte%s]",
1105         fragment_length, plurality(fragment_length, "", "s"));
1106   } else {
1107     col_append_fstr(pinfo->cinfo, COL_INFO, " EOT");
1108   }
1109
1110   if (cotp_reassemble) {
1111     /*
1112      * XXX - these sequence numbers are connection sequence number,
1113      * not segment sequence numbers - the first segment of a
1114      * segmented packet doesn't have a specific sequence number (e.g., 0
1115      * or 1), it has whatever the appropriate sequence number is for
1116      * it in the connection.
1117      *
1118      * For now, we assume segments arrive in order, and just supply
1119      * the negation of the EOT flag as the "more flags" argument.
1120      * We should probably handle out-of-order packets separately,
1121      * so that we can deliver them in order even when *not*
1122      * reassembling.
1123      *
1124      * Note also that TP0 has no sequence number, and relies on
1125      *      the protocol atop which it runs to guarantee in-order delivery.
1126      */
1127     fd_head = fragment_add_seq_next(&cotp_reassembly_table, next_tvb, 0, pinfo,
1128                                     dst_ref, NULL, fragment_length, fragment);
1129     if (fd_head && fd_head->next) {
1130       /* don't use -1 if fragment length is zero (throws Exception) */
1131       proto_tree_add_bytes_format(cotp_tree, hf_cotp_segment_data, tvb, offset, (fragment_length) ? -1 : 0,
1132                           NULL, "COTP segment data (%u byte%s)", fragment_length,
1133                           plurality(fragment_length, "", "s"));
1134
1135       if (!fragment) {
1136         /* This is the last packet */
1137         next_tvb = process_reassembled_data (next_tvb, offset, pinfo,
1138                                              "Reassembled COTP", fd_head,
1139                                              &cotp_frag_items, NULL, tree);
1140       } else if (pinfo->num != fd_head->reassembled_in) {
1141         /* Add a "Reassembled in" link if not reassembled in this frame */
1142         proto_tree_add_uint(cotp_tree, *(cotp_frag_items.hf_reassembled_in),
1143                             next_tvb, 0, 0, fd_head->reassembled_in);
1144       }
1145       pinfo->fragmented = fragment;
1146     }
1147   }
1148
1149   if (uses_inactive_subset) {
1150     if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
1151                                 pinfo, tree, &hdtbl_entry, NULL)) {
1152       *subdissector_found = TRUE;
1153     } else {
1154       /* Fill in other Dissectors using inactive subset here */
1155       call_data_dissector(next_tvb, pinfo, tree);
1156     }
1157   } else {
1158     /*
1159      * We dissect payload if one of the following is TRUE:
1160      *
1161      * - Reassembly option for COTP in preferences is unchecked
1162      * - Reassembly option is checked and this packet is the last fragment
1163      */
1164     if ((!cotp_reassemble) || ((cotp_reassemble) && (!fragment))) {
1165       if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1166                                   tree, &hdtbl_entry, NULL)) {
1167         *subdissector_found = TRUE;
1168       } else {
1169         call_data_dissector(next_tvb, pinfo, tree);
1170       }
1171     }
1172   }
1173
1174   offset += tvb_captured_length_remaining(tvb, offset);
1175   /* we dissected all of the containing PDU */
1176
1177   return offset;
1178
1179 } /* ositp_decode_DT */
1180
1181 static int ositp_decode_ED(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1182                            packet_info *pinfo, proto_tree *tree)
1183 {
1184   proto_tree *cotp_tree = NULL;
1185   proto_item *ti;
1186   gboolean    is_extended;
1187   guint16     dst_ref;
1188   guint       tpdu_nr;
1189   tvbuff_t   *next_tvb;
1190   guint       tpdu_len;
1191
1192   /* ED TPDUs have user data, so they run to the end of the containing PDU */
1193   tpdu_len = tvb_reported_length_remaining(tvb, offset);
1194
1195   /* note: in the ATN the user is up to chose between 3 different checksums:
1196    *       standard OSI, 2 or 4 octet extended checksum.
1197    * The differences for ED (as for DT) are that the TPDU headers may be
1198    * enlarged by 2 octets and that checksum related option codes and option
1199    * lengths are different.  To not mess up the original OSI dissector LI
1200    * checking was implemented separately.
1201    *
1202    * note: this could not be tested, because no sample was avail for expedited
1203    *       data */
1204   if (!cotp_decode_atn) {  /* non ATN, plain OSI*/
1205     /* ED TPDUs are never fragmented */
1206
1207     /* VP_CHECKSUM is the only parameter allowed in the variable part.
1208       (This means we may misdissect this if the packet is bad and
1209       contains other parameters.) */
1210     switch (li) {
1211
1212       case LI_NORMAL_DT_WITH_CHECKSUM      :
1213         if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
1214           return -1;
1215         /* FALLTHROUGH */
1216
1217       case LI_NORMAL_DT_WITHOUT_CHECKSUM   :
1218         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1219         if (tpdu_nr & 0x80)
1220           tpdu_nr = tpdu_nr & 0x7F;
1221         else
1222           return -1;
1223         is_extended = FALSE;
1224         break;
1225
1226       case LI_EXTENDED_DT_WITH_CHECKSUM    :
1227         if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
1228           return -1;
1229         /* FALLTHROUGH */
1230
1231       case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1232         tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1233         if (tpdu_nr & 0x80000000)
1234           tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1235         else
1236           return -1;
1237         is_extended = TRUE;
1238         break;
1239
1240       default : /* bad TPDU */
1241         return -1;
1242     } /* li */
1243   } else {
1244     /* check packet length indicators of ATN Expedited Data (ED) TPDU
1245      * note: use of checksum depends on the selected RER
1246      *       (high:non-use medium:16-bit OSI/16-bit ext.ATN low:32-bit ext. ATN)
1247      *
1248      * note: sole use of TP4 class in the ATN
1249      * note: normal/extended TPDU numbering is negociable */
1250     switch (li) {
1251
1252       case LI_NORMAL_DT_WITHOUT_CHECKSUM   :
1253         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1254         if (tpdu_nr & 0x80)
1255           tpdu_nr = tpdu_nr & 0x7F;
1256         else
1257           return -1;
1258         is_extended = FALSE;
1259         break;
1260
1261       case LI_NORMAL_DT_WITH_CHECKSUM      :
1262         if ((tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM) &&
1263              (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16))
1264           return -1;
1265
1266         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1267         if (tpdu_nr & 0x80)
1268           tpdu_nr = tpdu_nr & 0x7F;
1269         else
1270           return -1;
1271         is_extended = FALSE;
1272         break;
1273
1274       case LI_ATN_NORMAL_DT_WITH_CHECKSUM      :
1275         if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32)
1276           return -1;
1277
1278         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1279         if (tpdu_nr & 0x80)
1280           tpdu_nr = tpdu_nr & 0x7F;
1281         else
1282           return -1;
1283         is_extended = FALSE;
1284         break;
1285
1286       case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1287         tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1288         if (tpdu_nr & 0x80000000)
1289           tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1290         else
1291           return -1;
1292         is_extended = TRUE;
1293         break;
1294
1295       case LI_EXTENDED_DT_WITH_CHECKSUM    :
1296         if ((tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM) &&
1297               (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16))
1298           return -1;
1299
1300         tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1301         if (tpdu_nr & 0x80000000)
1302           tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1303         else
1304           return -1;
1305         is_extended = TRUE;
1306         break;
1307
1308       case LI_ATN_EXTENDED_DT_WITH_CHECKSUM    :
1309         if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32)
1310           return -1;
1311
1312         tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1313         if (tpdu_nr & 0x80000000)
1314           tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1315         else
1316           return -1;
1317         is_extended = TRUE;
1318         break;
1319
1320       default : /* bad TPDU */
1321         return -1;
1322     } /* li */
1323   } /* cotp_decode_atn */
1324
1325   dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1326   pinfo->clnp_dstref = dst_ref;
1327
1328   col_append_fstr(pinfo->cinfo, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
1329                   tpdu_nr, dst_ref);
1330
1331   if (tree) {
1332     ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1333     cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1334     proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1335   }
1336   offset += 1;
1337
1338   if (tree) {
1339     proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1340   }
1341   offset += 1;
1342   li -= 1;
1343
1344   if (tree)
1345     proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1346   offset += 2;
1347   li -= 2;
1348
1349   if (is_extended) {
1350     if (tree) {
1351       proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb, offset,
1352                           4, tpdu_nr);
1353     }
1354     offset += 4;
1355     li -= 4;
1356   } else {
1357     if (tree) {
1358       proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
1359                           tpdu_nr);
1360     }
1361     offset += 1;
1362     li -= 1;
1363   }
1364
1365   if (tree)
1366     ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1367   offset += li;
1368
1369   /*
1370    * XXX - hand this to subdissectors but tell them that this is
1371    * in an ED packet?
1372    */
1373   next_tvb = tvb_new_subset_remaining(tvb, offset);
1374   call_data_dissector(next_tvb, pinfo, tree);
1375
1376   offset += tvb_captured_length_remaining(tvb, offset);
1377      /* we dissected all of the containing PDU */
1378
1379   return offset;
1380
1381 } /* ositp_decode_ED */
1382
1383 static int ositp_decode_RJ(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1384                            guint8 cdt, packet_info *pinfo, proto_tree *tree)
1385 {
1386   proto_tree *cotp_tree;
1387   proto_item *ti;
1388   proto_item *item = NULL;
1389   guint16  dst_ref;
1390   guint    tpdu_nr;
1391   gushort  credit = 0;
1392
1393   /* note: in the ATN the user is up to chose between 3 different checksums:
1394    *       standard OSI, 2 or 4 octet extended checksum.
1395    * The difference for RJ is that the TPDU header may be enlarged by 2 octets
1396    * for checksum parameters are not going to be checked here */
1397   if (!cotp_decode_atn) {  /* non ATN, plain OSI */
1398     switch(li) {
1399       case LI_NORMAL_RJ   :
1400         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1401         break;
1402       case LI_EXTENDED_RJ :
1403         tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1404         credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
1405         break;
1406       default :
1407         return -1;
1408     }
1409   } else {
1410     switch(li) {
1411       /* normal with 2 octets of OSI or ATN checksum */
1412       case LI_NORMAL_RJ   :
1413       /* with 4 octets of ATN checksum */
1414       case LI_ATN_NORMAL_RJ   :
1415         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1416         break;
1417       /* extended with 2 octets of OSI or ATN checksum */
1418       case LI_EXTENDED_RJ :
1419       /* with 4 octets of ATN checksum */
1420       case LI_ATN_EXTENDED_RJ :
1421         tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1422         credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
1423         break;
1424       default :
1425         return -1;
1426     }
1427   }
1428
1429   dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1430   pinfo->clnp_dstref = dst_ref;
1431
1432   col_append_fstr(pinfo->cinfo, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
1433                   tpdu_nr, dst_ref);
1434
1435   if (tree) {
1436     ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1437     cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1438     proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1439     item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset +  1, 1,
1440                                tpdu);
1441     if (li == LI_NORMAL_RJ) {
1442       proto_tree_add_uint(cotp_tree, hf_cotp_credit_cdt, tvb, offset +  1, 1, cdt);
1443     }
1444     proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset +  2, 2,
1445                         dst_ref);
1446     if (li == LI_NORMAL_RJ)
1447       proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset + 4,
1448                           1, tpdu_nr);
1449     else {
1450       proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1451                           offset + 4, 4, tpdu_nr);
1452       proto_tree_add_uint(cotp_tree, hf_cotp_credit, tvb, offset +  8, 2, credit);
1453     }
1454   }
1455
1456   offset += li + 1;
1457
1458   expert_add_info_format(pinfo, item, &ei_cotp_reject, "Reject(RJ): -> 0x%x", dst_ref);
1459
1460   return offset;
1461
1462 } /* ositp_decode_RJ */
1463
1464 static int ositp_decode_CR_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1465                               packet_info *pinfo, proto_tree *tree,
1466                               gboolean uses_inactive_subset,
1467                               gboolean *subdissector_found)
1468 {
1469   /* note: in the ATN the user is up to chose between 3 different checksums:
1470    *       standard OSI, 2 or 4 octet extended checksum.
1471    * Nothing has to be done here, for all ATN specifics are handled in VP. */
1472
1473   /* CC & CR decoding in the same function */
1474
1475   proto_tree *cotp_tree = NULL;
1476   proto_item *ti;
1477   proto_item *item = NULL;
1478   guint16 dst_ref, src_ref;
1479   guint8  class_option;
1480   tvbuff_t *next_tvb;
1481   guint   tpdu_len;
1482   heur_dtbl_entry_t *hdtbl_entry;
1483   static const int * class_options[] = {
1484      &hf_cotp_class,
1485      &hf_cotp_opts_extended_formats,
1486      &hf_cotp_opts_no_explicit_flow_control,
1487      NULL,
1488   };
1489
1490   src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1491
1492   class_option = tvb_get_guint8(tvb, offset + P_CLASS_OPTION);
1493   if (((class_option & 0xF0) >> 4) > 4) /* class 0..4 allowed */
1494     return -1;
1495
1496   /* CR and CC TPDUs can have user data, so they run to the end of the
1497    * containing PDU */
1498   tpdu_len = tvb_reported_length_remaining(tvb, offset);
1499
1500   dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1501   pinfo->clnp_srcref = src_ref;
1502   pinfo->clnp_dstref = dst_ref;
1503
1504   col_append_fstr(pinfo->cinfo, COL_INFO,
1505                   "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1506                   (tpdu == CR_TPDU) ? "CR" : "CC", src_ref, dst_ref);
1507
1508   ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1509   cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1510   proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1511   offset += 1;
1512
1513   item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1514   offset += 1;
1515   li -= 1;
1516
1517   proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1518   offset += 2;
1519   li -= 2;
1520
1521   proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1522   offset += 2;
1523   li -= 2;
1524
1525   /* expert info, but only if not encapsulated in TCP/SMB */
1526   /* XXX - the best way to detect seems to be if we have a port set */
1527   if (pinfo->destport == 0) {
1528     expert_add_info_format(pinfo, item, &ei_cotp_connection, "Connection %s: 0x%x -> 0x%x", tpdu == CR_TPDU ? "Request(CR)" : "Confirm(CC)", src_ref, dst_ref);
1529   }
1530
1531   proto_tree_add_bitmask_list(cotp_tree, tvb, offset, 1, class_options, ENC_NA);
1532   offset += 1;
1533   li -= 1;
1534
1535   if (li > 0) {
1536     /* There's more data left, so we have the variable part.
1537
1538        Microsoft's RDP hijacks the variable part of CR and CC PDUs
1539        for their own user data (RDP runs atop Class 0, which doesn't
1540        support user data).
1541
1542        Try what heuristic dissectors we have. */
1543     next_tvb = tvb_new_subset_length(tvb, offset, li);
1544     if (dissector_try_heuristic((tpdu == CR_TPDU) ?
1545                                  cotp_cr_heur_subdissector_list :
1546                                  cotp_cc_heur_subdissector_list,
1547                                 next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
1548       /* A subdissector claimed this, so it really belongs to them. */
1549       *subdissector_found = TRUE;
1550     } else {
1551       /* No heuristic dissector claimed it, so dissect it as a regular
1552          variable part. */
1553       ositp_decode_var_part(tvb, offset, li, class_option, tpdu_len, pinfo,
1554                             cotp_tree);
1555     }
1556     offset += li;
1557   }
1558
1559   /*
1560    * XXX - tell the subdissector that this is user data in a CR or
1561    * CC packet rather than a DT packet?
1562    */
1563   if (tvb_captured_length_remaining(tvb, offset)) {
1564     next_tvb = tvb_new_subset_remaining(tvb, offset);
1565     if (!uses_inactive_subset){
1566       if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1567                                   tree, &hdtbl_entry, NULL)) {
1568         *subdissector_found = TRUE;
1569       } else {
1570         call_data_dissector(next_tvb, pinfo, tree);
1571       }
1572     }
1573     else
1574       call_data_dissector( next_tvb, pinfo, tree);
1575     offset += tvb_captured_length_remaining(tvb, offset);
1576     /* we dissected all of the containing PDU */
1577   }
1578
1579   return offset;
1580
1581 } /* ositp_decode_CR_CC */
1582
1583 static int ositp_decode_DC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1584                            packet_info *pinfo, proto_tree *tree)
1585 {
1586   proto_tree *cotp_tree = NULL;
1587   proto_item *ti;
1588   proto_item *item = NULL;
1589   guint16 dst_ref, src_ref;
1590   guint   tpdu_len;
1591
1592   /* ATN may use checksums different from OSI */
1593   /* which may result in different TPDU header length. */
1594   if (!cotp_decode_atn) {
1595     if (li > LI_MAX_DC)
1596       return -1;
1597   } else {
1598     if (li > LI_ATN_MAX_DC)
1599       return -1;
1600   }
1601
1602   /* DC TPDUs have no user data, so the length indicator determines the
1603    * length */
1604   tpdu_len = li + 1;
1605
1606   dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1607   src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1608   pinfo->clnp_dstref = dst_ref;
1609   pinfo->clnp_srcref = src_ref;
1610
1611   col_append_fstr(pinfo->cinfo, COL_INFO,
1612                   "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref, dst_ref);
1613
1614   if (tree) {
1615     ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1616     cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1617     proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1618   }
1619   offset += 1;
1620
1621   if (tree) {
1622     item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1623   }
1624   offset += 1;
1625   li -= 1;
1626
1627   if (tree)
1628     proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1629   offset += 2;
1630   li -= 2;
1631
1632   if (tree)
1633     proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1634   offset += 2;
1635   li -= 2;
1636
1637   if (tree)
1638     ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1639   offset += li;
1640
1641   expert_add_info_format(pinfo, item, &ei_cotp_disconnect_confirm, "Disconnect Confirm(DC): 0x%x -> 0x%x", src_ref, dst_ref);
1642
1643   return offset;
1644
1645 } /* ositp_decode_DC */
1646
1647 static int ositp_decode_AK(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1648                            guint8 cdt, packet_info *pinfo, proto_tree *tree)
1649 {
1650   proto_tree *cotp_tree = NULL;
1651   proto_item *ti;
1652   guint16    dst_ref;
1653   guint      tpdu_nr;
1654   gushort    cdt_in_ak;
1655   guint      tpdu_len;
1656
1657   if (!cotp_decode_atn) {
1658     if (li > LI_MAX_AK)
1659       return -1;
1660   } else {
1661     if (li > LI_ATN_MAX_AK)
1662       return -1;
1663   }
1664
1665   /* AK TPDUs have no user data, so the length indicator determines the
1666    * length */
1667   tpdu_len = li + 1;
1668
1669   /* is_LI_NORMAL_AK() works for normal ATN AK's, */
1670   /* for the TPDU header size may be enlarged by 2 octets */
1671   if (is_LI_NORMAL_AK(li)) {
1672
1673     dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1674     tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1675     pinfo->clnp_dstref = dst_ref;
1676
1677     col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1678                     tpdu_nr, dst_ref);
1679
1680     if (tree) {
1681       ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1682       cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1683       proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1684     }
1685     offset += 1;
1686
1687     if (tree) {
1688       proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1689       proto_tree_add_uint(cotp_tree, hf_cotp_credit_cdt, tvb, offset, 1, cdt);
1690     }
1691     offset += 1;
1692     li -= 1;
1693
1694     if (tree)
1695       proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1696     offset += 2;
1697     li -= 2;
1698
1699     if (tree) {
1700       proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
1701                           tpdu_nr);
1702     }
1703     offset += 1;
1704     li -= 1;
1705
1706     if (tree)
1707       ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1708     offset += li;
1709
1710   } else { /* extended format */
1711
1712     dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1713     tpdu_nr   = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1714     cdt_in_ak = tvb_get_ntohs(tvb, offset + P_CDT_IN_AK);
1715     pinfo->clnp_dstref = dst_ref;
1716
1717     col_append_fstr(pinfo->cinfo, COL_INFO,
1718                     "AK TPDU (%u) dst-ref: 0x%04x Credit: %u",
1719                     tpdu_nr, dst_ref, cdt_in_ak);
1720
1721     if (tree) {
1722       ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1723       cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1724       proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1725     }
1726     offset += 1;
1727
1728     if (tree) {
1729       proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1730     }
1731     offset += 1;
1732     li -= 1;
1733
1734     if (tree)
1735       proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1736     offset += 2;
1737     li -= 2;
1738
1739     if (tree) {
1740       proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1741                           offset, 4, tpdu_nr);
1742     }
1743     offset += 4;
1744     li -= 4;
1745
1746     if (tree) {
1747       proto_tree_add_uint(cotp_tree, hf_cotp_credit, tvb, offset, 2, cdt_in_ak);
1748     }
1749     offset += 2;
1750     li -= 2;
1751
1752     if (tree)
1753       ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1754     offset += li;
1755
1756   } /* is_LI_NORMAL_AK */
1757
1758   return offset;
1759
1760 } /* ositp_decode_AK */
1761
1762 static int ositp_decode_EA(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1763                            packet_info *pinfo, proto_tree *tree)
1764 {
1765   proto_tree *cotp_tree = NULL;
1766   proto_item *ti;
1767   gboolean is_extended;
1768   guint16  dst_ref;
1769   guint    tpdu_nr;
1770   guint    tpdu_len;
1771
1772   /* Due to different checksums in the ATN the TPDU header sizes
1773    * as well as the checksum parameters may be different than plain OSI EA
1774    * because these are heavily checked for EA these checks had to be
1775    * re-implemented.
1776    * note: this could not be tested, because no sample was avail for expedited
1777    *       data */
1778   if (!cotp_decode_atn) {
1779     if (li > LI_MAX_EA)
1780       return -1;
1781
1782     /* VP_CHECKSUM is the only parameter allowed in the variable part.
1783      (This means we may misdissect this if the packet is bad and
1784      contains other parameters.) */
1785     switch (li) {
1786
1787       case LI_NORMAL_EA_WITH_CHECKSUM      :
1788         if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM ||
1789           tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
1790             return -1;
1791         /* FALLTHROUGH */
1792
1793       case LI_NORMAL_EA_WITHOUT_CHECKSUM   :
1794         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1795         is_extended = FALSE;
1796         break;
1797
1798       case LI_EXTENDED_EA_WITH_CHECKSUM    :
1799         if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ||
1800             tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1801           return -1;
1802         /* FALLTHROUGH */
1803
1804       case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1805         tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1806         is_extended = TRUE;
1807         break;
1808
1809       default : /* bad TPDU */
1810         return -1;
1811     } /* li */
1812   } else { /* cotp_decode_atn */
1813     /* check for ATN length: TPDU may be 2 octets longer due to checksum */
1814     if (li > LI_ATN_MAX_EA)
1815       return -1;
1816
1817     switch (li) {
1818
1819       /* extended TPDU numbering EA with  no checksum  */
1820       case LI_NORMAL_EA_WITHOUT_CHECKSUM   :
1821         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1822         is_extended = FALSE;
1823         break;
1824
1825       /* normal TPDU numbering EA with 2 octets of OSI or ATN extended
1826        * checksum */
1827       case LI_NORMAL_EA_WITH_CHECKSUM      :
1828         /* check checksum parameter (in VP) parameter code octet */
1829         if ((tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM) &&
1830             (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16))
1831           return -1;
1832
1833         /* check checksum parameter (in VP) length octet */
1834         if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
1835           return -1;
1836
1837         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1838         is_extended = FALSE;
1839         break;
1840
1841       /* normal TPDU numbering EA with 4 octets of ATN extended checksum  */
1842       case LI_ATN_NORMAL_EA_WITH_CHECKSUM      :
1843         /* check checksum parameter (in VP) parameter code octet */
1844         if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32)
1845           return -1;
1846
1847         /* check checksum parameter (in VP) length octet */
1848         if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 4)
1849           return -1;
1850
1851         tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1852         is_extended = FALSE;
1853         break;
1854
1855       /* extended TPDU numbering EA with no checksum  */
1856       case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1857         tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1858         is_extended = TRUE;
1859         break;
1860
1861       /* extended TPDU numbering EA with 2 octets of OSI or ATN extended
1862        * checksum */
1863       case LI_EXTENDED_EA_WITH_CHECKSUM    :
1864         /* check checksum parameter (in VP) parameter code octet */
1865         if ((tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM) &&
1866              (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16))
1867           return -1;
1868
1869         /* check checksum parameter (in VP) length octet */
1870         if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1871           return -1;
1872
1873         tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1874         is_extended = TRUE;
1875         break;
1876
1877         /* extended EA with 4 octets ATN extended checksum  */
1878       case LI_ATN_EXTENDED_EA_WITH_CHECKSUM    :
1879         /* check checksum parameter (in VP) parameter code octet */
1880         if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32)
1881           return -1;
1882
1883         /* check checksum parameter (in VP) length octet */
1884         if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1885           return -1;
1886
1887         tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1888         is_extended = TRUE;
1889         break;
1890
1891       default : /* bad TPDU */
1892         return -1;
1893     }
1894   }
1895
1896   /* ER TPDUs have no user data, so the length indicator determines the
1897    * length */
1898   tpdu_len = li + 1;
1899
1900   dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1901   pinfo->clnp_dstref = dst_ref;
1902
1903   col_append_fstr(pinfo->cinfo, COL_INFO, "EA TPDU (%u) dst-ref: 0x%04x",
1904                   tpdu_nr, dst_ref);
1905
1906   if (tree) {
1907     ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1908     cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1909     proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1910   }
1911   offset += 1;
1912
1913   if (tree) {
1914     proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1915   }
1916   offset += 1;
1917   li -= 1;
1918
1919   if (tree)
1920     proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1921   offset += 2;
1922   li -= 2;
1923
1924   if (is_extended) {
1925     if (tree) {
1926       proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1927                           offset, 4, tpdu_nr);
1928     }
1929     offset += 4;
1930     li -= 4;
1931   } else {
1932     if (tree) {
1933       proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
1934                           tpdu_nr);
1935     }
1936     offset += 1;
1937     li -= 1;
1938   }
1939
1940   if (tree)
1941     ositp_decode_var_part(tvb, offset, li, 4, tpdu_len,  pinfo, cotp_tree);
1942   offset += li;
1943
1944   return offset;
1945
1946 } /* ositp_decode_EA */
1947
1948 static const value_string cotp_reject_vals[] = {
1949   { 0, "Reason not specified" },
1950   { 1, "Invalid parameter code" },
1951   { 2, "Invalid TPDU type" },
1952   { 3, "Invalid parameter value" },
1953   { 0,       NULL }
1954 };
1955
1956 static int ositp_decode_ER(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1957                            packet_info *pinfo, proto_tree *tree)
1958 {
1959   proto_tree *cotp_tree = NULL;
1960   proto_item *ti;
1961   guint16 dst_ref;
1962   guint8 tpdu_len;
1963
1964   /* ATN: except for modified LI checking nothing to be done here */
1965   if (!cotp_decode_atn) {
1966     if (li > LI_MAX_ER)
1967       return -1;
1968   } else {
1969     if (li > LI_ATN_MAX_ER)
1970       return -1;
1971   }
1972
1973   /* ER TPDUs have no user data, so the length indicator determines the
1974    * length */
1975   tpdu_len = li + 1;
1976
1977   if(try_val_to_str(tvb_get_guint8(tvb, offset + P_REJECT_ER), cotp_reject_vals) == NULL)
1978       return -1;
1979
1980   dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1981   pinfo->clnp_dstref = dst_ref;
1982
1983   col_append_fstr(pinfo->cinfo, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
1984
1985   if (tree) {
1986     ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1987     cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1988     proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1989     proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset +  1, 1, tpdu);
1990     proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset +  2, 2,
1991                         dst_ref);
1992     proto_tree_add_item(cotp_tree, hf_cotp_reject_cause, tvb, offset + 4, 1, ENC_NA);
1993   }
1994   offset += 5;
1995   li -= 4;
1996
1997   if (tree)
1998     ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1999   offset += li;
2000
2001   return offset;
2002
2003 } /* ositp_decode_ER */
2004
2005 static int ositp_decode_UD(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
2006                            packet_info *pinfo, proto_tree *tree,
2007                            gboolean *subdissector_found)
2008 {
2009   proto_item *ti;
2010   proto_tree *cltp_tree = NULL;
2011   tvbuff_t   *next_tvb;
2012   guint      tpdu_len;
2013   heur_dtbl_entry_t *hdtbl_entry;
2014
2015   /* UD TPDUs have user data, so they run to the end of the containing PDU */
2016   tpdu_len = tvb_reported_length_remaining(tvb, offset);
2017
2018   col_append_str(pinfo->cinfo, COL_INFO, "UD TPDU");
2019
2020   if (tree) {
2021     ti = proto_tree_add_item(tree, proto_cltp, tvb, offset, li + 1, ENC_NA);
2022     cltp_tree = proto_item_add_subtree(ti, ett_cltp);
2023     proto_tree_add_uint(cltp_tree, hf_cltp_li, tvb, offset, 1,li);
2024   }
2025   offset += 1;
2026
2027   if (tree) {
2028     proto_tree_add_uint(cltp_tree, hf_cltp_type, tvb, offset, 1, tpdu);
2029   }
2030   offset += 1;
2031   li -= 1;
2032
2033   if (tree)
2034     ositp_decode_var_part(tvb, offset, li, 0, tpdu_len, pinfo, cltp_tree);
2035   offset += li;
2036
2037   next_tvb = tvb_new_subset_remaining(tvb, offset);
2038
2039   if (dissector_try_heuristic(cltp_heur_subdissector_list, next_tvb,
2040                               pinfo, tree, &hdtbl_entry, NULL)) {
2041     *subdissector_found = TRUE;
2042   } else {
2043     call_data_dissector(next_tvb, pinfo, tree);
2044   }
2045
2046
2047   /*call_data_dissector(next_tvb, pinfo, tree); */
2048
2049   offset += tvb_captured_length_remaining(tvb, offset);
2050   /* we dissected all of the containing PDU */
2051
2052   return offset;
2053
2054 } /* ositp_decode_UD */
2055
2056 /* Returns the offset past the last valid COTP or CLTP PDU if we found
2057    at least one valid COTP or CLTP PDU, 0 otherwise.
2058
2059    There doesn't seem to be any way in which the OSI network layer protocol
2060    distinguishes between COTP and CLTP, but the first two octets of both
2061    protocols' headers mean the same thing - length and PDU type - and the
2062    only valid CLTP PDU type is not a valid COTP PDU type, so we'll handle
2063    both of them here. */
2064 static gint dissect_ositp_internal(tvbuff_t *tvb, packet_info *pinfo,
2065                                    proto_tree *tree,
2066                                    gboolean uses_inactive_subset)
2067 {
2068   int offset = 0;
2069   guint8 li, tpdu, cdt;
2070   gboolean first_tpdu = TRUE;
2071   int new_offset;
2072   gboolean found_ositp = FALSE;
2073   gboolean is_cltp = FALSE;
2074   gboolean subdissector_found = FALSE;
2075
2076   /* Initialize the COL_INFO field; each of the TPDUs will have its
2077      information appended. */
2078   col_set_str(pinfo->cinfo, COL_INFO, "");
2079
2080   while (tvb_offset_exists(tvb, offset)) {
2081     if (!first_tpdu) {
2082       col_append_str(pinfo->cinfo, COL_INFO, ", ");
2083       expert_add_info(pinfo, NULL, &ei_cotp_multiple_tpdus);
2084       /* adjust tvb and offset to the start of the current PDU */
2085       tvb = tvb_new_subset_remaining(tvb, offset);
2086       offset = 0 ;
2087     }
2088     if ((li = tvb_get_guint8(tvb, offset + P_LI)) == 0) {
2089       col_append_str(pinfo->cinfo, COL_INFO, "Length indicator is zero");
2090       if (!first_tpdu)
2091         call_data_dissector( tvb_new_subset_remaining(tvb, offset),
2092                        pinfo, tree);
2093       return found_ositp;
2094     }
2095
2096     tpdu = (tvb_get_guint8(tvb, offset + P_TPDU) >> 4) & 0x0F;
2097     if (tpdu == UD_TPDU)
2098       pinfo->current_proto = "CLTP";    /* connectionless transport */
2099     cdt = tvb_get_guint8(tvb, offset + P_CDT) & 0x0F;
2100
2101     switch (tpdu) {
2102       case CC_TPDU :
2103       case CR_TPDU :
2104         new_offset = ositp_decode_CR_CC(tvb, offset, li, tpdu, pinfo, tree,
2105                                         uses_inactive_subset, &subdissector_found);
2106         break;
2107       case DR_TPDU :
2108         new_offset = ositp_decode_DR(tvb, offset, li, tpdu, pinfo, tree);
2109         break;
2110       case DT_TPDU :
2111         new_offset = ositp_decode_DT(tvb, offset, li, tpdu, pinfo, tree,
2112                                      uses_inactive_subset, &subdissector_found);
2113         break;
2114       case ED_TPDU :
2115         new_offset = ositp_decode_ED(tvb, offset, li, tpdu, pinfo, tree);
2116         break;
2117       case RJ_TPDU :
2118         new_offset = ositp_decode_RJ(tvb, offset, li, tpdu, cdt, pinfo, tree);
2119         break;
2120       case DC_TPDU :
2121         new_offset = ositp_decode_DC(tvb, offset, li, tpdu, pinfo, tree);
2122         break;
2123       case AK_TPDU :
2124         new_offset = ositp_decode_AK(tvb, offset, li, tpdu, cdt, pinfo, tree);
2125         break;
2126       case EA_TPDU :
2127         new_offset = ositp_decode_EA(tvb, offset, li, tpdu, pinfo, tree);
2128         break;
2129       case ER_TPDU :
2130         new_offset = ositp_decode_ER(tvb, offset, li, tpdu, pinfo, tree);
2131         break;
2132       case UD_TPDU :
2133         new_offset = ositp_decode_UD(tvb, offset, li, tpdu, pinfo, tree,
2134                                      &subdissector_found);
2135         is_cltp = TRUE;
2136         break;
2137       default      :
2138         if (first_tpdu)
2139           col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TPDU type (0x%x)",
2140                           tpdu);
2141         new_offset = -1;    /* bad PDU type */
2142         break;
2143     }
2144
2145     if (new_offset == -1) { /* incorrect TPDU */
2146       if (!first_tpdu)
2147         call_data_dissector( tvb_new_subset_remaining(tvb, offset),
2148                        pinfo, tree);
2149       break;
2150     }
2151
2152     if (first_tpdu) {
2153       /* Well, we found at least one valid COTP or CLTP PDU, so I guess this
2154          is either COTP or CLTP. */
2155       if (!subdissector_found)
2156         col_set_str(pinfo->cinfo, COL_PROTOCOL, is_cltp ? "CLTP" : "COTP");
2157       found_ositp = TRUE;
2158     }
2159
2160     offset = new_offset;
2161     first_tpdu = FALSE;
2162   }
2163   return found_ositp ? offset : 0;
2164 } /* dissect_ositp_internal */
2165
2166 static gint dissect_ositp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2167                           void *data _U_)
2168 {
2169   return dissect_ositp_internal(tvb, pinfo, tree, FALSE);
2170 }
2171
2172 static gint dissect_ositp_inactive(tvbuff_t *tvb, packet_info *pinfo,
2173                                    proto_tree *tree, void *data _U_)
2174 {
2175   return dissect_ositp_internal(tvb, pinfo, tree, TRUE);
2176 }
2177
2178 static void
2179 cotp_reassemble_init(void)
2180 {
2181   cotp_dst_ref = 0;
2182 }
2183
2184 void proto_register_cotp(void)
2185 {
2186   static hf_register_info hf[] = {
2187     { &hf_cotp_li,
2188       { "Length", "cotp.li", FT_UINT8, BASE_DEC,
2189         NULL, 0x0, "Length Indicator, length of this header", HFILL}},
2190     { &hf_cotp_type,
2191       { "PDU Type", "cotp.type", FT_UINT8, BASE_HEX,
2192         VALS(cotp_tpdu_type_abbrev_vals), 0x0,
2193         "PDU Type - upper nibble of byte", HFILL}},
2194     { &hf_cotp_srcref,
2195       { "Source reference", "cotp.srcref", FT_UINT16, BASE_HEX,
2196         NULL, 0x0, "Source address reference", HFILL}},
2197     { &hf_cotp_destref,
2198       { "Destination reference", "cotp.destref", FT_UINT16, BASE_HEX,
2199         NULL, 0x0, "Destination address reference", HFILL}},
2200     { &hf_cotp_class,
2201       { "Class", "cotp.class", FT_UINT8, BASE_DEC, NULL,
2202         0xF0, "Transport protocol class", HFILL}},
2203     { &hf_cotp_opts_extended_formats,
2204       { "Extended formats", "cotp.opts.extended_formats", FT_BOOLEAN, 8,
2205         NULL, 0x02, "Use of extended formats in classes 2, 3, and 4", HFILL}},
2206     { &hf_cotp_opts_no_explicit_flow_control,
2207       { "No explicit flow control", "cotp.opts.no_explicit_flow_control",
2208         FT_BOOLEAN, 8, NULL, 0x01, "No explicit flow control in class 2",
2209         HFILL}},
2210     { &hf_cotp_tpdu_number,
2211       { "TPDU number", "cotp.tpdu-number", FT_UINT8, BASE_HEX,
2212         NULL, 0x7f, NULL, HFILL}},
2213     { &hf_cotp_tpdu_number_extended,
2214       { "TPDU number", "cotp.tpdu-number", FT_UINT32, BASE_HEX,
2215         NULL, 0x0 /* XXX - 0x7fff? */, NULL, HFILL}},
2216     { &hf_cotp_next_tpdu_number,
2217       { "Your TPDU number", "cotp.next-tpdu-number", FT_UINT8, BASE_HEX,
2218         NULL, 0x0, NULL, HFILL}},
2219     { &hf_cotp_next_tpdu_number_extended,
2220       { "Your TPDU number", "cotp.next-tpdu-number", FT_UINT32, BASE_HEX,
2221         NULL, 0x0, NULL, HFILL}},
2222     { &hf_cotp_eot,
2223       { "Last data unit", "cotp.eot", FT_BOOLEAN, 8,
2224         TFS(&tfs_yes_no),  0x80,
2225         "Is current TPDU the last data unit of a complete DT TPDU sequence "
2226         "(End of TSDU)?", HFILL}},
2227     { &hf_cotp_eot_extended,
2228       { "Last data unit", "cotp.eot", FT_BOOLEAN, 32,
2229         TFS(&tfs_yes_no),  0x80000000,
2230         "Is current TPDU the last data unit of a complete DT TPDU sequence "
2231         "(End of TSDU)?", HFILL}},
2232     { &hf_cotp_segment_overlap,
2233       { "Segment overlap", "cotp.segment.overlap", FT_BOOLEAN, BASE_NONE,
2234         NULL, 0x0, "Segment overlaps with other segments", HFILL }},
2235     { &hf_cotp_segment_overlap_conflict,
2236       { "Conflicting data in segment overlap", "cotp.segment.overlap.conflict",
2237         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2238         "Overlapping segments contained conflicting data", HFILL }},
2239     { &hf_cotp_segment_multiple_tails,
2240       { "Multiple tail segments found", "cotp.segment.multipletails",
2241         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2242         "Several tails were found when reassembling the packet", HFILL }},
2243     { &hf_cotp_segment_too_long_segment,
2244       { "Segment too long", "cotp.segment.toolongsegment",
2245         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2246         "Segment contained data past end of packet", HFILL }},
2247     { &hf_cotp_segment_error,
2248       { "Reassembly error", "cotp.segment.error", FT_FRAMENUM, BASE_NONE,
2249         NULL, 0x0, "Reassembly error due to illegal segments", HFILL }},
2250     { &hf_cotp_segment_count,
2251       { "Segment count", "cotp.segment.count", FT_UINT32, BASE_DEC,
2252         NULL, 0x0, NULL, HFILL }},
2253     { &hf_cotp_segment,
2254       { "COTP Segment", "cotp.segment", FT_FRAMENUM, BASE_NONE,
2255         NULL, 0x0, NULL, HFILL }},
2256     { &hf_cotp_segments,
2257       { "COTP Segments", "cotp.segments", FT_NONE, BASE_NONE,
2258         NULL, 0x0, NULL, HFILL }},
2259     { &hf_cotp_reassembled_in,
2260       { "Reassembled COTP in frame", "cotp.reassembled_in",
2261         FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2262         "This COTP packet is reassembled in this frame", HFILL }},
2263     { &hf_cotp_reassembled_length,
2264       { "Reassembled COTP length", "cotp.reassembled.length",
2265         FT_UINT32, BASE_DEC, NULL, 0x0,
2266         "The total length of the reassembled payload", HFILL }},
2267 /* ISO DP 8073 i13.3.4(a) Source and destination TSAPs are defined as
2268    identifiers of unspecified type and length.
2269    Some implementations of COTP use printable strings, others use raw bytes.
2270    We always add both representations to the tree; one will always be hidden
2271    depending on the tsap display preference */
2272     { &hf_cotp_vp_src_tsap,
2273       { "Source TSAP", "cotp.src-tsap", FT_STRING, BASE_NONE,
2274         NULL, 0x0, "Calling TSAP", HFILL }},
2275     { &hf_cotp_vp_src_tsap_bytes,
2276       { "Source TSAP", "cotp.src-tsap-bytes", FT_BYTES, BASE_NONE,
2277         NULL, 0x0, "Calling TSAP (bytes representation)", HFILL }},
2278     { &hf_cotp_vp_dst_tsap,
2279       { "Destination TSAP", "cotp.dst-tsap", FT_STRING, BASE_NONE,
2280         NULL, 0x0, "Called TSAP", HFILL }},
2281     { &hf_cotp_vp_dst_tsap_bytes,
2282       { "Destination TSAP", "cotp.dst-tsap-bytes", FT_BYTES, BASE_NONE,
2283         NULL, 0x0, "Called TSAP (bytes representation)", HFILL }},
2284       /* Generated from convert_proto_tree_add_text.pl */
2285       { &hf_cotp_parameter_code, { "Parameter code", "cotp.parameter_code", FT_UINT8, BASE_HEX, VALS(tp_vpart_type_vals), 0x0, NULL, HFILL }},
2286       { &hf_cotp_parameter_length, { "Parameter length", "cotp.parameter_length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2287       { &hf_cotp_parameter_value, { "Parameter value", "cotp.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2288       { &hf_cotp_atn_extended_checksum16, { "ATN extended checksum", "cotp.atn_extended_checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2289       { &hf_cotp_atn_extended_checksum32, { "ATN extended checksum", "cotp.atn_extended_checksum", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2290       { &hf_cotp_atn_extended_checksum_status, { "ATN extended checksum Status", "cotp.atn_extended_checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }},
2291       { &hf_cotp_ack_time, { "Ack time (ms)", "cotp.ack_time", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2292       { &hf_cotp_res_error_rate_target_value, { "Residual error rate, target value", "cotp.res_error_rate.target_value", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2293       { &hf_cotp_res_error_rate_min_accept, { "Residual error rate, minimum acceptable", "cotp.res_error_rate.min_accept", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2294       { &hf_cotp_res_error_rate_tdsu, { "Residual error rate, TSDU size of interest", "cotp.res_error_rate.tdsu", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2295       { &hf_cotp_vp_priority, { "Priority", "cotp.vp_priority", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2296       { &hf_cotp_transit_delay_targ_calling_called, { "Transit delay, target value, calling-called (ms)", "cotp.transit_delay.targ_calling_called", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2297       { &hf_cotp_transit_delay_max_accept_calling_called, { "Transit delay, maximum acceptable, calling-called (ms)", "cotp.transit_delay.max_accept_calling_called", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2298       { &hf_cotp_transit_delay_targ_called_calling, { "Transit delay, target value, called-calling (ms)", "cotp.transit_delay.targ_called_calling", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2299       { &hf_cotp_transit_delay_max_accept_called_calling, { "Transit delay, maximum acceptable, called-calling (ms)", "cotp.transit_delay.max_accept_called_calling", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2300       { &hf_cotp_max_throughput_targ_calling_called, { "Maximum throughput, target value, calling-called (o/s)", "cotp.max_throughput.targ_calling_called", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2301       { &hf_cotp_max_throughput_min_accept_calling_called, { "Maximum throughput, minimum acceptable, calling-called (o/s)", "cotp.max_throughput.min_accept_calling_called", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2302       { &hf_cotp_max_throughput_targ_called_calling, { "Maximum throughput, target value, called-calling (o/s)", "cotp.max_throughput.targ_called_calling", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2303       { &hf_cotp_max_throughput_min_accept_called_calling, { "Maximum throughput, minimum acceptable, called-calling (o/s)", "cotp.max_throughput.min_accept_called_calling", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2304       { &hf_cotp_avg_throughput_targ_calling_called, { "Average throughput, target value, calling-called (o/s)", "cotp.avg_throughput.targ_calling_called", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2305       { &hf_cotp_avg_throughput_min_accept_calling_called, { "Average throughput, minimum acceptable, calling-called (o/s)", "cotp.avg_throughput.min_accept_calling_called", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2306       { &hf_cotp_avg_throughput_targ_called_calling, { "Average throughput, target value, called-calling (o/s)", "cotp.avg_throughput.targ_called_calling", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2307       { &hf_cotp_avg_throughput_min_accept_called_calling, { "Average throughput, minimum acceptable, called-calling (o/s)", "cotp.avg_throughput.min_accept_called_calling", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2308       { &hf_cotp_sequence_number, { "Sequence number", "cotp.sequence_number", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2309       { &hf_cotp_reassignment_time, { "Reassignment time (secs)", "cotp.reassignment_time", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2310       { &hf_cotp_lower_window_edge, { "Lower window edge", "cotp.lower_window_edge", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2311       { &hf_cotp_credit, { "Credit", "cotp.credit", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2312       { &hf_cotp_tpdu_size, { "TPDU size", "cotp.tpdu_size", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2313       { &hf_cotp_checksum, { "Checksum", "cotp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2314       { &hf_cotp_checksum_status, { "Checksum Status", "cotp.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }},
2315       { &hf_cotp_vp_version_nr, { "Version", "cotp.vp_version_nr", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2316       { &hf_cotp_network_expedited_data, { "Use of network expedited data", "cotp.network_expedited_data", FT_BOOLEAN, 8, TFS(&tfs_used_notused), 0x08, NULL, HFILL }},
2317       { &hf_cotp_vp_opt_sel_class1_use, { "Use", "cotp.vp_opt_sel_class1_use", FT_BOOLEAN, 8, TFS(&tfs_vp_opt_sel_class1_use), 0x04, NULL, HFILL }},
2318       { &hf_cotp_use_16_bit_checksum, { "16 bit checksum", "cotp.use_16_bit_checksum", FT_BOOLEAN, 8, TFS(&tfs_used_notused), 0x02, NULL, HFILL }},
2319       { &hf_cotp_transport_expedited_data_transfer, { "Transport expedited data transfer", "cotp.transport_expedited_data_transfer", FT_BOOLEAN, 8, TFS(&tfs_used_notused), 0x01, NULL, HFILL }},
2320       { &hf_cotp_preferred_maximum_tpdu_size, { "Preferred maximum TPDU size", "cotp.preferred_maximum_tpdu_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2321       { &hf_cotp_inactivity_timer, { "Inactivity timer (ms)", "cotp.inactivity_timer", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2322       { &hf_cotp_cause, { "Cause", "cotp.cause", FT_UINT8, BASE_DEC, VALS(cotp_cause_vals), 0x0, NULL, HFILL }},
2323       { &hf_cotp_segment_data, { "COTP segment data", "cotp.segment_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2324       { &hf_cotp_credit_cdt, { "Credit", "cotp.credit", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2325       { &hf_cotp_reject_cause, { "Reject cause", "cotp.reject_cause", FT_UINT8, BASE_DEC, VALS(cotp_reject_vals), 0x0, NULL, HFILL }},
2326   };
2327   static gint *ett[] = {
2328     &ett_cotp,
2329     &ett_cotp_segment,
2330     &ett_cotp_segments
2331   };
2332   static ei_register_info ei[] = {
2333       { &ei_cotp_disconnect_request, { "cotp.disconnect_request", PI_SEQUENCE, PI_CHAT, "Disconnect Request(DR): 0x%x -> 0x%x", EXPFILL }},
2334       { &ei_cotp_reject, { "cotp.reject", PI_SEQUENCE, PI_NOTE, "Reject(RJ): -> 0x%x", EXPFILL }},
2335       { &ei_cotp_connection, { "cotp.connection", PI_SEQUENCE, PI_CHAT, "Connection %s: 0x%x -> 0x%x", EXPFILL }},
2336       { &ei_cotp_disconnect_confirm, { "cotp.disconnect_confirm", PI_SEQUENCE, PI_CHAT, "Disconnect Confirm(DC): 0x%x -> 0x%x", EXPFILL }},
2337       { &ei_cotp_multiple_tpdus, { "cotp.multiple_tpdus", PI_SEQUENCE, PI_NOTE, "Multiple TPDUs in one packet", EXPFILL }},
2338       { &ei_cotp_preferred_maximum_tpdu_size, { "cotp.preferred_maximum_tpdu_size.invalid", PI_PROTOCOL, PI_WARN, "Preferred maximum TPDU size: bogus length", EXPFILL }},
2339       { &ei_cotp_atn_extended_checksum, { "cotp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
2340       { &ei_cotp_checksum, { "cotp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
2341   };
2342
2343   module_t *cotp_module;
2344   expert_module_t* expert_cotp;
2345
2346   proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "COTP", "cotp");
2347   proto_register_field_array(proto_cotp, hf, array_length(hf));
2348   proto_register_subtree_array(ett, array_length(ett));
2349   expert_cotp = expert_register_protocol(proto_cotp);
2350   expert_register_field_array(expert_cotp, ei, array_length(ei));
2351   cotp_module = prefs_register_protocol(proto_cotp, NULL);
2352
2353   prefs_register_bool_preference(cotp_module, "reassemble",
2354                                  "Reassemble segmented COTP datagrams",
2355                                  "Whether segmented COTP datagrams should be "
2356                                  "reassembled. To use this option, you must "
2357                                  "also enable \"Allow subdissectors to "
2358                                  "reassemble TCP streams\" in the TCP "
2359                                  "protocol settings.",
2360                                  &cotp_reassemble);
2361
2362   prefs_register_enum_preference(cotp_module, "tsap_display",
2363                                  "Display TSAPs as strings or bytes",
2364                                  "How TSAPs should be displayed",
2365                                  &tsap_display, tsap_display_options, FALSE);
2366
2367   prefs_register_bool_preference(cotp_module, "decode_atn", "Decode ATN TPDUs",
2368                                  "Whether to decode OSI TPDUs with ATN "
2369                                  "(Aereonautical Telecommunications Network) "
2370                                  "extensions. To use this option, you must "
2371                                  "also enable \"Always try to decode NSDU as "
2372                                  "transport PDUs\" in the CLNP protocol "
2373                                  "settings.", &cotp_decode_atn);
2374
2375   /* For handling protocols hijacking the variable part of CR or CC PDUs */
2376   cotp_cr_heur_subdissector_list = register_heur_dissector_list("cotp_cr", proto_cotp);
2377   cotp_cc_heur_subdissector_list = register_heur_dissector_list("cotp_cc", proto_cotp);
2378
2379   /* subdissector code in inactive subset */
2380   cotp_is_heur_subdissector_list = register_heur_dissector_list("cotp_is", proto_cotp);
2381
2382   /* other COTP/ISO 8473 subdissectors */
2383   cotp_heur_subdissector_list = register_heur_dissector_list("cotp", proto_cotp);
2384
2385   /* XXX - what about CLTP and proto_cltp? */
2386   ositp_handle = register_dissector("ositp", dissect_ositp, proto_cotp);
2387   register_dissector("ositp_inactive", dissect_ositp_inactive, proto_cotp);
2388
2389   register_init_routine(cotp_reassemble_init);
2390   /*
2391    * XXX - this is a connection-oriented transport-layer protocol,
2392    * so we should probably use more than just network-layer
2393    * endpoint addresses to match segments together, but the functions
2394    * in addresses_ports_reassembly_table_functions do matching based
2395    * on port numbers, so they won't let us ensure that segments from
2396    * different connections don't get assembled together.
2397    */
2398   reassembly_table_register(&cotp_reassembly_table,
2399                         &addresses_reassembly_table_functions);
2400 }
2401
2402 void proto_register_cltp(void)
2403 {
2404   static hf_register_info hf[] = {
2405     { &hf_cltp_li,
2406       { "Length", "cltp.li", FT_UINT8, BASE_DEC, NULL, 0x0,
2407         "Length Indicator, length of this header", HFILL}},
2408     { &hf_cltp_type,
2409       { "PDU Type", "cltp.type", FT_UINT8, BASE_HEX,
2410         VALS(cltp_tpdu_type_abbrev_vals), 0x0, NULL, HFILL}}
2411   };
2412   static gint *ett[] = {
2413     &ett_cltp
2414   };
2415
2416   proto_cltp = proto_register_protocol(PROTO_STRING_CLTP, "CLTP", "cltp");
2417   proto_register_field_array(proto_cltp, hf, array_length(hf));
2418   proto_register_subtree_array(ett, array_length(ett));
2419
2420   cltp_heur_subdissector_list = register_heur_dissector_list("cltp", proto_cltp);
2421 }
2422
2423 void
2424 proto_reg_handoff_cotp(void)
2425 {
2426   dissector_add_uint("ip.proto", IP_PROTO_TP, ositp_handle);
2427
2428   rdp_cr_handle = find_dissector("rdp_cr");
2429   rdp_cc_handle = find_dissector("rdp_cc");
2430
2431   proto_clnp = proto_get_id_by_filter_name("clnp");
2432 }
2433
2434 /*
2435  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2436  *
2437  * Local variables:
2438  * c-basic-offset: 2
2439  * tab-width: 8
2440  * indent-tabs-mode: nil
2441  * End:
2442  *
2443  * vi: set shiftwidth=2 tabstop=8 expandtab:
2444  * :indentSize=2:tabSize=8:noTabs=true:
2445  */