epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-clnp.c
blobc9b06b455710291c5f475a4d280a23a5e8984bf9
1 /* packet-clnp.c
2 * Routines for ISO/OSI network protocol packet disassembly
4 * Laurent Deniel <laurent.deniel@free.fr>
5 * Ralf Schneider <Ralf.Schneider@t-online.de>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include "config.h"
16 #include <epan/packet.h>
17 #include <epan/prefs.h>
18 #include <epan/reassemble.h>
19 #include <epan/expert.h>
20 #include <epan/nlpid.h>
21 #include <epan/tfs.h>
23 #include "packet-osi.h"
24 #include "packet-osi-options.h"
26 void proto_register_clnp(void);
27 void proto_reg_handoff_clnp(void);
29 /* protocols and fields */
31 static int proto_clnp;
32 static int ett_clnp;
33 static int ett_clnp_type;
34 static int ett_clnp_segments;
35 static int ett_clnp_segment;
36 static int ett_clnp_disc_pdu;
38 static int hf_clnp_id;
39 static int hf_clnp_length;
40 static int hf_clnp_version;
41 static int hf_clnp_ttl;
42 static int hf_clnp_type;
43 static int hf_clnp_cnf_segmentation;
44 static int hf_clnp_cnf_more_segments;
45 static int hf_clnp_cnf_report_error;
46 static int hf_clnp_cnf_type;
47 static int hf_clnp_pdu_length;
48 static int hf_clnp_data_unit_identifier;
49 static int hf_clnp_segment_offset;
50 static int hf_clnp_total_length;
51 static int hf_clnp_checksum;
52 static int hf_clnp_checksum_status;
53 static int hf_clnp_dest_length;
54 static int hf_clnp_dest;
55 static int hf_clnp_src_length;
56 static int hf_clnp_src;
57 static int hf_clnp_segments;
58 static int hf_clnp_segment;
59 static int hf_clnp_segment_overlap;
60 static int hf_clnp_segment_overlap_conflict;
61 static int hf_clnp_segment_multiple_tails;
62 static int hf_clnp_segment_too_long_segment;
63 static int hf_clnp_segment_error;
64 static int hf_clnp_segment_count;
65 static int hf_clnp_reassembled_in;
66 static int hf_clnp_reassembled_length;
68 static const fragment_items clnp_frag_items = {
69 &ett_clnp_segment,
70 &ett_clnp_segments,
71 &hf_clnp_segments,
72 &hf_clnp_segment,
73 &hf_clnp_segment_overlap,
74 &hf_clnp_segment_overlap_conflict,
75 &hf_clnp_segment_multiple_tails,
76 &hf_clnp_segment_too_long_segment,
77 &hf_clnp_segment_error,
78 &hf_clnp_segment_count,
79 &hf_clnp_reassembled_in,
80 &hf_clnp_reassembled_length,
81 /* Reassembled data field */
82 NULL,
83 "segments"
86 static expert_field ei_clnp_length;
87 static expert_field ei_clnp_checksum;
89 static dissector_handle_t clnp_handle;
90 static dissector_handle_t ositp_handle;
91 static dissector_handle_t ositp_inactive_handle;
92 static dissector_handle_t idrp_handle;
95 * ISO 8473 OSI CLNP definition (see RFC994)
97 * _________________________________
98 * | Fixed Part |
99 * |_________________________________|
100 * | Address Part |
101 * |_________________________________|
102 * | Segmentation Part (optional) |
103 * |_________________________________|
104 * | Options Part (optional) |
105 * |_________________________________|
106 * | Data (optional) |
107 * |_________________________________|
110 #define ISO8473_V1 0x01 /* CLNP version 1 */
112 /* Fixed part */
114 /* Length of fixed part */
115 #define FIXED_PART_LEN 9
117 #define CNF_TYPE 0x1f
118 #define CNF_ERR_OK 0x20
119 #define CNF_MORE_SEGS 0x40
120 #define CNF_SEG_OK 0x80
122 #define DT_NPDU 0x1C
123 #define MD_NPDU 0x1D
124 #define ER_NPDU 0x01
125 #define ERQ_NPDU 0x1E
126 #define ERP_NPDU 0x1F
128 static const value_string npdu_type_abbrev_vals[] = {
129 { DT_NPDU, "DT" },
130 { MD_NPDU, "MD" },
131 { ER_NPDU, "ER" },
132 { ERQ_NPDU, "ERQ" },
133 { ERP_NPDU, "ERP" },
134 { 0, NULL }
137 static const value_string npdu_type_vals[] = {
138 { DT_NPDU, "Data" },
139 { MD_NPDU, "Multicast Data" },
140 { ER_NPDU, "Error Report" },
141 { ERQ_NPDU, "Echo Request" },
142 { ERP_NPDU, "Echo Response" },
143 { 0, NULL }
146 /* field position */
148 #define P_CLNP_PROTO_ID 0
149 #define P_CLNP_HDR_LEN 1
150 #define P_CLNP_VERS 2
151 #define P_CLNP_TTL 3
152 #define P_CLNP_TYPE 4
153 #define P_CLNP_SEGLEN 5
154 #define P_CLNP_CKSUM 7
155 #define P_CLNP_ADDRESS_PART 9
157 /* Segmentation part */
159 #define SEGMENTATION_PART_LEN 6
161 struct clnp_segment {
162 uint16_t cng_id; /* data unit identifier */
163 uint16_t cng_off; /* segment offset */
164 uint16_t cng_tot_len; /* total length */
167 /* NSAP selector */
169 #define NSEL_NET 0x00
170 #define NSEL_NP 0x20
171 #define NSEL_TP 0x21
173 /* global variables */
175 /* List of dissectors to call for CLNP packets */
176 static heur_dissector_list_t clnp_heur_subdissector_list;
179 * Reassembly of CLNP.
181 static reassembly_table clnp_reassembly_table;
183 /* options */
184 static unsigned tp_nsap_selector = NSEL_TP;
185 static bool always_decode_transport;
186 static bool clnp_reassemble = true;
188 /* function definitions */
191 * CLNP part / main entry point
194 static int
195 dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
197 proto_tree *clnp_tree;
198 proto_item *ti, *ti_len = NULL, *ti_pdu_len = NULL, *ti_tot_len = NULL;
199 uint8_t cnf_proto_id;
200 uint8_t cnf_hdr_len;
201 uint8_t cnf_vers;
202 uint8_t cnf_ttl;
203 uint8_t cnf_type;
204 char flag_string[6+1];
205 const char *pdu_type_string;
206 proto_tree *type_tree;
207 uint16_t segment_length;
208 uint16_t du_id = 0;
209 uint16_t segment_offset = 0;
210 uint16_t total_length;
211 uint16_t cnf_cksum;
212 bool cksum_valid = true;
213 int offset;
214 unsigned char src_len, dst_len, nsel, opt_len = 0;
215 unsigned next_length;
216 proto_tree *discpdu_tree;
217 bool save_in_error_pkt;
218 fragment_head *fd_head;
219 tvbuff_t *next_tvb;
220 bool update_col_info = true;
221 bool save_fragmented;
222 heur_dtbl_entry_t *hdtbl_entry;
224 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CLNP");
225 col_clear(pinfo->cinfo, COL_INFO);
227 cnf_proto_id = tvb_get_uint8(tvb, P_CLNP_PROTO_ID);
228 if (cnf_proto_id == NLPID_NULL) {
229 col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset");
230 ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, ENC_NA);
231 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
232 proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
233 cnf_proto_id, "Inactive subset");
234 next_tvb = tvb_new_subset_remaining(tvb, 1);
235 call_dissector(ositp_inactive_handle, next_tvb, pinfo, tree);
236 return tvb_captured_length(tvb);
239 /* return if version not known */
240 cnf_vers = tvb_get_uint8(tvb, P_CLNP_VERS);
241 if (cnf_vers != ISO8473_V1) {
242 call_data_dissector(tvb, pinfo, tree);
243 return tvb_captured_length(tvb);
246 /* fixed part decoding */
247 cnf_hdr_len = tvb_get_uint8(tvb, P_CLNP_HDR_LEN);
249 ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA);
250 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
251 proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
252 cnf_proto_id);
253 ti_len = proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
254 cnf_hdr_len);
255 if (cnf_hdr_len < FIXED_PART_LEN) {
256 /* Header length is less than the length of the fixed part of
257 the header. */
258 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
259 "Header length value < minimum length %u",
260 FIXED_PART_LEN);
261 return 2;
263 proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
264 cnf_vers);
265 cnf_ttl = tvb_get_uint8(tvb, P_CLNP_TTL);
266 proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
267 cnf_ttl,
268 "Holding Time : %u (%u.%u secs)",
269 cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
270 cnf_type = tvb_get_uint8(tvb, P_CLNP_TYPE);
271 pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
272 "Unknown (0x%02x)");
273 flag_string[0] = '\0';
274 if (cnf_type & CNF_SEG_OK)
275 (void) g_strlcat(flag_string, "S ", 7);
276 if (cnf_type & CNF_MORE_SEGS)
277 (void) g_strlcat(flag_string, "M ", 7);
278 if (cnf_type & CNF_ERR_OK)
279 (void) g_strlcat(flag_string, "E ", 7);
280 ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
281 cnf_type,
282 "PDU Type : 0x%02x (%s%s)",
283 cnf_type,
284 flag_string,
285 pdu_type_string);
286 type_tree = proto_item_add_subtree(ti, ett_clnp_type);
287 proto_tree_add_item(type_tree, hf_clnp_cnf_segmentation, tvb, P_CLNP_TYPE, 1, ENC_NA);
288 proto_tree_add_item(type_tree, hf_clnp_cnf_more_segments, tvb, P_CLNP_TYPE, 1, ENC_NA);
289 proto_tree_add_item(type_tree, hf_clnp_cnf_report_error, tvb, P_CLNP_TYPE, 1, ENC_NA);
290 proto_tree_add_item(type_tree, hf_clnp_cnf_type, tvb, P_CLNP_TYPE, 1, ENC_BIG_ENDIAN);
292 /* If we don't have the full header - i.e., not enough to see the
293 segmentation part and determine whether this datagram is segmented
294 or not - set the Info column now; we'll get an exception before
295 we set it otherwise. */
297 if (tvb_reported_length(tvb) < cnf_hdr_len) {
298 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
301 segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
302 ti_pdu_len = proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
303 segment_length);
304 if (segment_length < cnf_hdr_len) {
305 /* Segment length is less than the header length. */
306 expert_add_info_format(pinfo, ti_pdu_len, &ei_clnp_length,
307 "PDU length < header length %u", cnf_hdr_len);
308 return 7;
310 cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
311 if (cnf_cksum == 0) {
312 /* No checksum present */
313 proto_tree_add_checksum(clnp_tree, tvb, P_CLNP_CKSUM, hf_clnp_checksum, hf_clnp_checksum_status, &ei_clnp_checksum, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NOT_PRESENT);
314 } else {
315 uint32_t c0 = 0, c1 = 0;
317 if (osi_calc_checksum(tvb, 0, cnf_hdr_len, &c0, &c1)) {
318 /* Successfully processed checksum, verify it */
319 proto_tree_add_checksum(clnp_tree, tvb, P_CLNP_CKSUM, hf_clnp_checksum, hf_clnp_checksum_status, &ei_clnp_checksum, pinfo, c0 | c1, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_ZERO);
320 cksum_valid = (c0 | c1) ? false : true;
321 } else {
322 proto_tree_add_checksum(clnp_tree, tvb, P_CLNP_CKSUM, hf_clnp_checksum, hf_clnp_checksum_status, &ei_clnp_checksum, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
326 opt_len = cnf_hdr_len;
327 opt_len -= FIXED_PART_LEN; /* Fixed part of Header */
329 /* address part */
331 offset = P_CLNP_ADDRESS_PART;
332 if (opt_len < 1) {
333 /* Header length is less than the minimum value in CLNP,
334 including the destination address length. */
335 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
336 "Header length value < %u",
337 FIXED_PART_LEN + 1);
338 return offset;
340 dst_len = tvb_get_uint8(tvb, offset);
341 if (tree) {
342 proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
343 dst_len);
345 offset += 1;
346 opt_len -= 1;
348 if (opt_len < dst_len) {
349 /* Header length is less than the minimum value,
350 including the destination address length and the
351 destination address. */
352 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
353 "Header length value < %u",
354 FIXED_PART_LEN + 1 + dst_len);
355 return offset;
357 nsel = tvb_get_uint8(tvb, offset + dst_len - 1);
358 set_address_tvb(&pinfo->net_dst, get_osi_address_type(), dst_len, tvb, offset);
359 copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
360 proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_dest, tvb, offset, dst_len,
361 NULL,
362 "%s",
363 print_nsap_net(pinfo->pool, tvb, offset, dst_len));
364 offset += dst_len;
365 opt_len -= dst_len;
367 if (opt_len < 1) {
368 /* Header length is less than the minimum value,
369 including the destination address length, the
370 destination address, and the source address length. */
371 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
372 "Header length value < %u",
373 FIXED_PART_LEN + 1 + dst_len + 1);
374 return offset;
376 src_len = tvb_get_uint8(tvb, offset);
377 if (tree) {
378 proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
379 offset, 1, src_len);
381 offset += 1;
382 opt_len -= 1;
384 if (opt_len < src_len) {
385 /* Header length is less than the minimum value,
386 including the destination address length, the
387 destination address, the source address length,
388 and the source address. */
389 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
390 "Header length value < %u",
391 FIXED_PART_LEN + 1 + dst_len + 1 + src_len);
392 return offset;
394 set_address_tvb(&pinfo->net_src, get_osi_address_type(), src_len, tvb, offset);
395 copy_address_shallow(&pinfo->src, &pinfo->net_src);
396 proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_src, tvb, offset, src_len,
397 NULL,
398 "%s",
399 print_nsap_net(pinfo->pool, tvb, offset, src_len));
400 offset += src_len;
401 opt_len -= src_len;
403 /* Segmentation Part */
405 if (cnf_type & CNF_SEG_OK) {
406 if (opt_len < SEGMENTATION_PART_LEN) {
407 /* Header length is less than the minimum value,
408 including the destination address length, the
409 destination address, the source address length,
410 the source address, and the segmentation part. */
411 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
412 "Header length value < %u",
413 FIXED_PART_LEN + 1 + dst_len + 1 + SEGMENTATION_PART_LEN);
414 return offset;
417 du_id = tvb_get_ntohs(tvb, offset);
418 proto_tree_add_item(clnp_tree, hf_clnp_data_unit_identifier, tvb, offset, 2, ENC_BIG_ENDIAN);
419 segment_offset = tvb_get_ntohs(tvb, offset + 2);
420 proto_tree_add_item(clnp_tree, hf_clnp_segment_offset, tvb, offset + 2 , 2, ENC_BIG_ENDIAN);
421 total_length = tvb_get_ntohs(tvb, offset + 4);
422 ti_tot_len = proto_tree_add_item(clnp_tree, hf_clnp_total_length, tvb, offset + 4 , 2, ENC_BIG_ENDIAN);
423 if (total_length < segment_length) {
424 /* Reassembled length is less than the length of this segment. */
425 expert_add_info_format(pinfo, ti_tot_len, &ei_clnp_length,
426 "Total length < segment length %u", segment_length);
427 return offset;
429 offset += SEGMENTATION_PART_LEN;
430 opt_len -= SEGMENTATION_PART_LEN;
433 dissect_osi_options(opt_len, tvb, offset, clnp_tree, pinfo);
435 offset += opt_len;
437 /* If clnp_reassemble is on, this is a segment, we have all the
438 * data in the segment, and the checksum is valid, then just add the
439 * segment to the hashtable.
441 save_fragmented = pinfo->fragmented;
442 if (clnp_reassemble && (cnf_type & CNF_SEG_OK) &&
443 ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) &&
444 tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) &&
445 segment_length > cnf_hdr_len &&
446 cksum_valid != false) {
447 fd_head = fragment_add_check(&clnp_reassembly_table,
448 tvb, offset, pinfo, du_id, NULL,
449 segment_offset, segment_length - cnf_hdr_len,
450 cnf_type & CNF_MORE_SEGS);
452 next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP",
453 fd_head, &clnp_frag_items, &update_col_info, clnp_tree);
454 } else {
455 /* If this is the first segment, dissect its contents, otherwise
456 just show it as a segment.
458 XXX - if we eventually don't save the reassembled contents of all
459 segmented datagrams, we may want to always reassemble. */
460 if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) {
461 /* Not the first segment - don't dissect it. */
462 next_tvb = NULL;
463 } else {
464 /* First segment, or not segmented. Dissect what we have here. */
466 /* Get a tvbuff for the payload. Set its length to the segment
467 length, and flag it as a fragment, so going past the end
468 reports FragmentBoundsError, i.e. "there's data missing
469 because this isn't reassembled", not ReportedBoundsError,
470 i.e. "the dissector ran past the end of the packet, so the
471 packet must not have been constructed properly". */
472 next_tvb = tvb_new_subset_length(tvb, offset, segment_length - cnf_hdr_len);
473 tvb_set_fragment(next_tvb);
476 * If this is the first segment, but not the only segment,
477 * tell the next protocol that.
479 if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS))
480 pinfo->fragmented = true;
481 else
482 pinfo->fragmented = false;
486 if (next_tvb == NULL) {
487 /* Just show this as a segment. */
488 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
489 pdu_type_string, flag_string, segment_offset);
491 /* As we haven't reassembled anything, we haven't changed "pi", so
492 we don't have to restore it. */
493 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
494 pinfo->fragmented = save_fragmented;
495 return tvb_captured_length(tvb);
498 if (tvb_offset_exists(tvb, offset)) {
499 switch (cnf_type & CNF_TYPE) {
501 case DT_NPDU:
502 case MD_NPDU:
503 /* Continue with COTP if any data.
504 XXX - if this isn't the first Derived PDU of a segmented Initial
505 PDU, skip that? */
507 if (nsel==NSEL_NET && tvb_get_uint8(next_tvb, 0)==NLPID_ISO10747_IDRP) {
508 if(call_dissector(idrp_handle, next_tvb, pinfo, tree) != 0) {
509 pinfo->fragmented = save_fragmented;
510 return tvb_captured_length(tvb);
513 if (nsel == (unsigned char)tp_nsap_selector || always_decode_transport) {
514 if (call_dissector(ositp_handle, next_tvb, pinfo, tree) != 0) {
515 pinfo->fragmented = save_fragmented;
516 return tvb_captured_length(tvb); /* yes, it appears to be COTP or CLTP */
519 if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb,
520 pinfo, tree, &hdtbl_entry, NULL)) {
521 pinfo->fragmented = save_fragmented;
522 return tvb_captured_length(tvb); /* yes, it appears to be one of the protocols in the heuristic list */
525 break;
527 case ER_NPDU:
528 /* The payload is the header and "none, some, or all of the data
529 part of the discarded PDU", i.e. it's like an ICMP error;
530 dissect it as a CLNP PDU. */
532 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
533 next_length = tvb_reported_length_remaining(tvb, offset);
534 if (next_length != 0) {
535 /* We have payload; dissect it. */
536 discpdu_tree = proto_tree_add_subtree(clnp_tree, tvb, offset, next_length,
537 ett_clnp_disc_pdu, NULL, "Discarded PDU");
539 /* Save the current value of the "we're inside an error packet"
540 flag, and set that flag; subdissectors may treat packets
541 that are the payload of error packets differently from
542 "real" packets. */
543 save_in_error_pkt = pinfo->flags.in_error_pkt;
544 pinfo->flags.in_error_pkt = true;
546 call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);
548 /* Restore the "we're inside an error packet" flag. */
549 pinfo->flags.in_error_pkt = save_in_error_pkt;
551 pinfo->fragmented = save_fragmented;
552 return tvb_captured_length(tvb); /* we're done with this PDU */
554 case ERQ_NPDU:
555 case ERP_NPDU:
556 /* XXX - dissect this */
557 break;
560 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
561 call_data_dissector(next_tvb, pinfo, tree);
562 pinfo->fragmented = save_fragmented;
563 return tvb_captured_length(tvb);
564 } /* dissect_clnp */
566 void
567 proto_register_clnp(void)
569 static hf_register_info hf[] = {
570 { &hf_clnp_id,
571 { "Network Layer Protocol Identifier", "clnp.nlpi", FT_UINT8, BASE_HEX,
572 VALS(nlpid_vals), 0x0, NULL, HFILL }},
574 { &hf_clnp_length,
575 { "HDR Length", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
577 { &hf_clnp_version,
578 { "Version", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
580 { &hf_clnp_ttl,
581 { "Holding Time", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
583 { &hf_clnp_type,
584 { "PDU Type", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
586 { &hf_clnp_cnf_segmentation,
587 { "Segmentation permitted", "clnp.cnf.segmentation", FT_BOOLEAN, 8, TFS(&tfs_yes_no), CNF_SEG_OK, NULL, HFILL }},
589 { &hf_clnp_cnf_more_segments,
590 { "More segments", "clnp.cnf.more_segments", FT_BOOLEAN, 8, TFS(&tfs_yes_no), CNF_MORE_SEGS, NULL, HFILL }},
592 { &hf_clnp_cnf_report_error,
593 { "Report error if PDU discarded", "clnp.cnf.report_error", FT_BOOLEAN, 8, TFS(&tfs_yes_no), CNF_ERR_OK, NULL, HFILL }},
595 { &hf_clnp_cnf_type,
596 { "Type", "clnp.cnf.type", FT_UINT8, BASE_DEC, VALS(npdu_type_vals), CNF_TYPE, NULL, HFILL }},
598 { &hf_clnp_pdu_length,
599 { "PDU length", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
601 { &hf_clnp_data_unit_identifier,
602 { "Data unit identifier", "clnp.data_unit_identifier", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
604 { &hf_clnp_segment_offset,
605 { "Segment offset", "clnp.segment_offset", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
607 { &hf_clnp_total_length,
608 { "Total length", "clnp.total_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
610 { &hf_clnp_checksum,
611 { "Checksum", "clnp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
613 { &hf_clnp_checksum_status,
614 { "Checksum Status", "clnp.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }},
616 { &hf_clnp_dest_length,
617 { "DAL", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
619 { &hf_clnp_dest,
620 { "DA", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
622 { &hf_clnp_src_length,
623 { "SAL", "clnp.ssap.len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
625 { &hf_clnp_src,
626 { "SA", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
628 { &hf_clnp_segment_overlap,
629 { "Segment overlap", "clnp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
630 "Segment overlaps with other segments", HFILL }},
632 { &hf_clnp_segment_overlap_conflict,
633 { "Conflicting data in segment overlap", "clnp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
634 "Overlapping segments contained conflicting data", HFILL }},
636 { &hf_clnp_segment_multiple_tails,
637 { "Multiple tail segments found", "clnp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
638 "Several tails were found when reassembling the packet", HFILL }},
640 { &hf_clnp_segment_too_long_segment,
641 { "Segment too long", "clnp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
642 "Segment contained data past end of packet", HFILL }},
644 { &hf_clnp_segment_error,
645 { "Reassembly error", "clnp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
646 "Reassembly error due to illegal segments", HFILL }},
648 { &hf_clnp_segment_count,
649 { "Segment count", "clnp.segment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
650 NULL, HFILL }},
652 { &hf_clnp_segment,
653 { "CLNP Segment", "clnp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
654 NULL, HFILL }},
656 { &hf_clnp_segments,
657 { "CLNP Segments", "clnp.segments", FT_NONE, BASE_NONE, NULL, 0x0,
658 NULL, HFILL }},
660 { &hf_clnp_reassembled_in,
661 { "Reassembled CLNP in frame", "clnp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
662 "This CLNP packet is reassembled in this frame", HFILL }},
664 { &hf_clnp_reassembled_length,
665 { "Reassembled CLNP length", "clnp.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
666 "The total length of the reassembled payload", HFILL }}
668 static int *ett[] = {
669 &ett_clnp,
670 &ett_clnp_type,
671 &ett_clnp_segments,
672 &ett_clnp_segment,
673 &ett_clnp_disc_pdu,
676 static ei_register_info ei[] = {
677 { &ei_clnp_length, { "clnp.len.bad", PI_MALFORMED, PI_ERROR, "Header length value bad", EXPFILL }},
678 { &ei_clnp_checksum, { "clnp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
681 module_t *clnp_module;
682 expert_module_t* expert_clnp;
684 proto_clnp = proto_register_protocol(PROTO_STRING_CLNP, "CLNP", "clnp");
685 proto_register_field_array(proto_clnp, hf, array_length(hf));
686 proto_register_subtree_array(ett, array_length(ett));
687 expert_clnp = expert_register_protocol(proto_clnp);
688 expert_register_field_array(expert_clnp, ei, array_length(ei));
689 clnp_handle = register_dissector("clnp", dissect_clnp, proto_clnp);
690 clnp_heur_subdissector_list = register_heur_dissector_list_with_description("clnp", "CLNP DT/MD payload", proto_clnp);
692 reassembly_table_register(&clnp_reassembly_table,
693 &addresses_reassembly_table_functions);
695 register_osi_address_type();
697 clnp_module = prefs_register_protocol(proto_clnp, NULL);
698 prefs_register_uint_preference(clnp_module, "tp_nsap_selector",
699 "NSAP selector for Transport Protocol (last byte in hex)",
700 "NSAP selector for Transport Protocol (last byte in hex)",
701 16, &tp_nsap_selector);
702 prefs_register_bool_preference(clnp_module, "always_decode_transport",
703 "Always try to decode NSDU as transport PDUs",
704 "Always try to decode NSDU as transport PDUs",
705 &always_decode_transport);
706 prefs_register_bool_preference(clnp_module, "reassemble",
707 "Reassemble segmented CLNP datagrams",
708 "Whether segmented CLNP datagrams should be reassembled",
709 &clnp_reassemble);
710 /* XXX - catch this and tweak the decode_as settings? */
711 prefs_register_obsolete_preference(clnp_module, "decode_atn_options");
714 void
715 proto_reg_handoff_clnp(void)
717 ositp_handle = find_dissector_add_dependency("ositp", proto_clnp);
718 ositp_inactive_handle = find_dissector_add_dependency("ositp_inactive", proto_clnp);
719 idrp_handle = find_dissector_add_dependency("idrp", proto_clnp);
721 dissector_add_uint("osinl.incl", NLPID_ISO8473_CLNP, clnp_handle);
722 dissector_add_uint("osinl.incl", NLPID_NULL, clnp_handle); /* Inactive subset */
723 dissector_add_uint("x.25.spi", NLPID_ISO8473_CLNP, clnp_handle);
727 * Editor modelines - https://www.wireshark.org/tools/modelines.html
729 * Local variables:
730 * c-basic-offset: 4
731 * tab-width: 8
732 * indent-tabs-mode: nil
733 * End:
735 * vi: set shiftwidth=4 tabstop=8 expandtab:
736 * :indentSize=4:tabSize=8:noTabs=true: