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 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <epan/packet.h>
29 #include <epan/prefs.h>
30 #include <epan/reassemble.h>
31 #include <epan/expert.h>
32 #include <epan/nlpid.h>
34 #include "packet-osi.h"
35 #include "packet-osi-options.h"
37 void proto_register_clnp(void);
38 void proto_reg_handoff_clnp(void);
40 /* protocols and fields */
42 static int proto_clnp = -1;
43 static gint ett_clnp = -1;
44 static gint ett_clnp_type = -1;
45 static gint ett_clnp_segments = -1;
46 static gint ett_clnp_segment = -1;
47 static gint ett_clnp_disc_pdu = -1;
49 static int hf_clnp_id = -1;
50 static int hf_clnp_length = -1;
51 static int hf_clnp_version = -1;
52 static int hf_clnp_ttl = -1;
53 static int hf_clnp_type = -1;
54 static int hf_clnp_cnf_segmentation = -1;
55 static int hf_clnp_cnf_more_segments = -1;
56 static int hf_clnp_cnf_report_error = -1;
57 static int hf_clnp_cnf_type = -1;
58 static int hf_clnp_pdu_length = -1;
59 static int hf_clnp_data_unit_identifier = -1;
60 static int hf_clnp_segment_offset = -1;
61 static int hf_clnp_total_length = -1;
62 static int hf_clnp_checksum = -1;
63 static int hf_clnp_dest_length = -1;
64 static int hf_clnp_dest = -1;
65 static int hf_clnp_src_length = -1;
66 static int hf_clnp_src = -1;
67 int hf_clnp_atntt = -1; /* as referenced in packet-osi-options.c */
68 int hf_clnp_atnsc = -1; /* as referenced in packet-osi-options.c */
69 static int hf_clnp_segments = -1;
70 static int hf_clnp_segment = -1;
71 static int hf_clnp_segment_overlap = -1;
72 static int hf_clnp_segment_overlap_conflict = -1;
73 static int hf_clnp_segment_multiple_tails = -1;
74 static int hf_clnp_segment_too_long_segment = -1;
75 static int hf_clnp_segment_error = -1;
76 static int hf_clnp_segment_count = -1;
77 static int hf_clnp_reassembled_in = -1;
78 static int hf_clnp_reassembled_length = -1;
80 static const fragment_items clnp_frag_items = {
85 &hf_clnp_segment_overlap,
86 &hf_clnp_segment_overlap_conflict,
87 &hf_clnp_segment_multiple_tails,
88 &hf_clnp_segment_too_long_segment,
89 &hf_clnp_segment_error,
90 &hf_clnp_segment_count,
91 &hf_clnp_reassembled_in,
92 &hf_clnp_reassembled_length,
93 /* Reassembled data field */
98 static expert_field ei_clnp_length = EI_INIT;
100 static dissector_handle_t clnp_handle;
101 static dissector_handle_t ositp_handle;
102 static dissector_handle_t ositp_inactive_handle;
103 static dissector_handle_t idrp_handle;
104 static dissector_handle_t data_handle;
107 * ISO 8473 OSI CLNP definition (see RFC994)
109 * _________________________________
111 * |_________________________________|
113 * |_________________________________|
114 * | Segmentation Part (optional) |
115 * |_________________________________|
116 * | Options Part (optional) |
117 * |_________________________________|
118 * | Data (optional) |
119 * |_________________________________|
122 #define ISO8473_V1 0x01 /* CLNP version 1 */
126 /* Length of fixed part */
127 #define FIXED_PART_LEN 9
129 #define CNF_TYPE 0x1f
130 #define CNF_ERR_OK 0x20
131 #define CNF_MORE_SEGS 0x40
132 #define CNF_SEG_OK 0x80
137 #define ERQ_NPDU 0x1E
138 #define ERP_NPDU 0x1F
140 static const value_string npdu_type_abbrev_vals[] = {
149 static const value_string npdu_type_vals[] = {
151 { MD_NPDU, "Multicast Data" },
152 { ER_NPDU, "Error Report" },
153 { ERQ_NPDU, "Echo Request" },
154 { ERP_NPDU, "Echo Response" },
160 #define P_CLNP_PROTO_ID 0
161 #define P_CLNP_HDR_LEN 1
162 #define P_CLNP_VERS 2
164 #define P_CLNP_TYPE 4
165 #define P_CLNP_SEGLEN 5
166 #define P_CLNP_CKSUM 7
167 #define P_CLNP_ADDRESS_PART 9
169 /* Segmentation part */
171 #define SEGMENTATION_PART_LEN 6
173 struct clnp_segment {
174 gushort cng_id; /* data unit identifier */
175 gushort cng_off; /* segment offset */
176 gushort cng_tot_len; /* total length */
181 #define NSEL_NET 0x00
185 /* global variables */
187 /* List of dissectors to call for CLNP packets */
188 static heur_dissector_list_t clnp_heur_subdissector_list;
191 * Reassembly of CLNP.
193 static reassembly_table clnp_reassembly_table;
196 static guint tp_nsap_selector = NSEL_TP;
197 static gboolean always_decode_transport = FALSE;
198 static gboolean clnp_reassemble = TRUE;
199 gboolean clnp_decode_atn_options = FALSE;
201 /* function definitions */
204 * CLNP part / main entry point
208 dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
210 proto_tree *clnp_tree;
211 proto_item *ti, *ti_len = NULL, *ti_pdu_len = NULL, *ti_tot_len = NULL;
217 char flag_string[6+1];
218 const char *pdu_type_string;
219 proto_tree *type_tree;
220 guint16 segment_length;
222 guint16 segment_offset = 0;
223 guint16 total_length;
225 cksum_status_t cksum_status;
227 guchar src_len, dst_len, nsel, opt_len = 0;
229 proto_tree *discpdu_tree;
230 gboolean save_in_error_pkt;
231 fragment_head *fd_head;
233 gboolean update_col_info = TRUE;
234 gboolean save_fragmented;
235 heur_dtbl_entry_t *hdtbl_entry;
237 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CLNP");
238 col_clear(pinfo->cinfo, COL_INFO);
240 cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID);
241 if (cnf_proto_id == NLPID_NULL) {
242 col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset");
243 ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, ENC_NA);
244 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
245 proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
246 cnf_proto_id, "Inactive subset");
247 next_tvb = tvb_new_subset_remaining(tvb, 1);
248 if (call_dissector(ositp_inactive_handle, next_tvb, pinfo, tree) == 0)
249 call_dissector(data_handle,tvb, pinfo, tree);
250 return tvb_captured_length(tvb);
253 /* return if version not known */
254 cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS);
255 if (cnf_vers != ISO8473_V1) {
256 call_dissector(data_handle,tvb, pinfo, tree);
257 return tvb_captured_length(tvb);
260 /* fixed part decoding */
261 cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
263 ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA);
264 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
265 proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
267 ti_len = proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
269 if (cnf_hdr_len < FIXED_PART_LEN) {
270 /* Header length is less than the length of the fixed part of
272 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
273 "Header length value < minimum length %u",
277 proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
279 cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
280 proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
282 "Holding Time : %u (%u.%u secs)",
283 cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
284 cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
285 pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
287 flag_string[0] = '\0';
288 if (cnf_type & CNF_SEG_OK)
289 g_strlcat(flag_string, "S ", 7);
290 if (cnf_type & CNF_MORE_SEGS)
291 g_strlcat(flag_string, "M ", 7);
292 if (cnf_type & CNF_ERR_OK)
293 g_strlcat(flag_string, "E ", 7);
294 ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
296 "PDU Type : 0x%02x (%s%s)",
300 type_tree = proto_item_add_subtree(ti, ett_clnp_type);
301 proto_tree_add_item(type_tree, hf_clnp_cnf_segmentation, tvb, P_CLNP_TYPE, 1, ENC_NA);
302 proto_tree_add_item(type_tree, hf_clnp_cnf_more_segments, tvb, P_CLNP_TYPE, 1, ENC_NA);
303 proto_tree_add_item(type_tree, hf_clnp_cnf_report_error, tvb, P_CLNP_TYPE, 1, ENC_NA);
304 proto_tree_add_item(type_tree, hf_clnp_cnf_type, tvb, P_CLNP_TYPE, 1, ENC_BIG_ENDIAN);
306 /* If we don't have the full header - i.e., not enough to see the
307 segmentation part and determine whether this datagram is segmented
308 or not - set the Info column now; we'll get an exception before
309 we set it otherwise. */
311 if (tvb_reported_length(tvb) < cnf_hdr_len) {
312 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
315 segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
316 ti_pdu_len = proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
318 if (segment_length < cnf_hdr_len) {
319 /* Segment length is less than the header length. */
320 expert_add_info_format(pinfo, ti_pdu_len, &ei_clnp_length,
321 "PDU length < header length %u", cnf_hdr_len);
324 cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
325 cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum);
326 switch (cksum_status) {
329 * No checksum present, or not enough of the header present to
332 proto_tree_add_uint(clnp_tree, hf_clnp_checksum, tvb,
339 * Checksum is correct.
341 proto_tree_add_uint_format_value(clnp_tree, hf_clnp_checksum, tvb,
350 * Checksum is not correct.
352 proto_tree_add_uint_format_value(clnp_tree, hf_clnp_checksum, tvb,
355 "0x%04x (incorrect)",
360 opt_len = cnf_hdr_len;
361 opt_len -= FIXED_PART_LEN; /* Fixed part of Header */
365 offset = P_CLNP_ADDRESS_PART;
367 /* Header length is less than the minimum value in CLNP,
368 including the destination address length. */
369 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
370 "Header length value < %u",
374 dst_len = tvb_get_guint8(tvb, offset);
376 proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
382 if (opt_len < dst_len) {
383 /* Header length is less than the minimum value,
384 including the destination address length and the
385 destination address. */
386 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
387 "Header length value < %u",
388 FIXED_PART_LEN + 1 + dst_len);
391 nsel = tvb_get_guint8(tvb, offset + dst_len - 1);
392 set_address_tvb(&pinfo->net_dst, get_osi_address_type(), dst_len, tvb, offset);
393 copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
394 proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_dest, tvb, offset, dst_len,
397 print_nsap_net(tvb, offset, dst_len));
402 /* Header length is less than the minimum value,
403 including the destination address length, the
404 destination address, and the source address length. */
405 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
406 "Header length value < %u",
407 FIXED_PART_LEN + 1 + dst_len + 1);
410 src_len = tvb_get_guint8(tvb, offset);
412 proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
418 if (opt_len < src_len) {
419 /* Header length is less than the minimum value,
420 including the destination address length, the
421 destination address, the source address length,
422 and the source address. */
423 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
424 "Header length value < %u",
425 FIXED_PART_LEN + 1 + dst_len + 1 + src_len);
428 set_address_tvb(&pinfo->net_src, get_osi_address_type(), src_len, tvb, offset);
429 copy_address_shallow(&pinfo->src, &pinfo->net_src);
430 proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_src, tvb,
434 print_nsap_net(tvb, offset, src_len));
439 /* Segmentation Part */
441 if (cnf_type & CNF_SEG_OK) {
442 if (opt_len < SEGMENTATION_PART_LEN) {
443 /* Header length is less than the minimum value,
444 including the destination address length, the
445 destination address, the source address length,
446 the source address, and the segmentation part. */
447 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
448 "Header length value < %u",
449 FIXED_PART_LEN + 1 + dst_len + 1 + SEGMENTATION_PART_LEN);
453 du_id = tvb_get_ntohs(tvb, offset);
454 proto_tree_add_item(clnp_tree, hf_clnp_data_unit_identifier, tvb, offset, 2, ENC_BIG_ENDIAN);
455 segment_offset = tvb_get_ntohs(tvb, offset + 2);
456 proto_tree_add_item(clnp_tree, hf_clnp_segment_offset, tvb, offset + 2 , 2, ENC_BIG_ENDIAN);
457 total_length = tvb_get_ntohs(tvb, offset + 4);
458 ti_tot_len = proto_tree_add_item(clnp_tree, hf_clnp_total_length, tvb, offset + 4 , 2, ENC_BIG_ENDIAN);
459 if (total_length < segment_length) {
460 /* Reassembled length is less than the length of this segment. */
461 expert_add_info_format(pinfo, ti_tot_len, &ei_clnp_length,
462 "Total length < segment length %u", segment_length);
465 offset += SEGMENTATION_PART_LEN;
466 opt_len -= SEGMENTATION_PART_LEN;
469 dissect_osi_options(opt_len, tvb, offset, clnp_tree, pinfo);
473 /* If clnp_reassemble is on, this is a segment, we have all the
474 * data in the segment, and the checksum is valid, then just add the
475 * segment to the hashtable.
477 save_fragmented = pinfo->fragmented;
478 if (clnp_reassemble && (cnf_type & CNF_SEG_OK) &&
479 ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) &&
480 tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) &&
481 segment_length > cnf_hdr_len &&
482 cksum_status != CKSUM_NOT_OK) {
483 fd_head = fragment_add_check(&clnp_reassembly_table,
484 tvb, offset, pinfo, du_id, NULL,
485 segment_offset, segment_length - cnf_hdr_len,
486 cnf_type & CNF_MORE_SEGS);
488 next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP",
489 fd_head, &clnp_frag_items, &update_col_info, clnp_tree);
491 /* If this is the first segment, dissect its contents, otherwise
492 just show it as a segment.
494 XXX - if we eventually don't save the reassembled contents of all
495 segmented datagrams, we may want to always reassemble. */
496 if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) {
497 /* Not the first segment - don't dissect it. */
500 /* First segment, or not segmented. Dissect what we have here. */
502 /* Get a tvbuff for the payload. Set its length to the segment
503 length, and flag it as a fragment, so going past the end
504 reports FragmentBoundsError, i.e. "there's data missing
505 because this isn't reassembled", not ReportedBoundsError,
506 i.e. "the dissector ran past the end of the packet, so the
507 packet must not have been constructed properly". */
508 next_tvb = tvb_new_subset_length(tvb, offset, segment_length - cnf_hdr_len);
509 tvb_set_fragment(next_tvb);
512 * If this is the first segment, but not the only segment,
513 * tell the next protocol that.
515 if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS))
516 pinfo->fragmented = TRUE;
518 pinfo->fragmented = FALSE;
522 if (next_tvb == NULL) {
523 /* Just show this as a segment. */
524 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
525 pdu_type_string, flag_string, segment_offset);
527 /* As we haven't reassembled anything, we haven't changed "pi", so
528 we don't have to restore it. */
529 call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo,
531 pinfo->fragmented = save_fragmented;
532 return tvb_captured_length(tvb);
535 if (tvb_offset_exists(tvb, offset)) {
536 switch (cnf_type & CNF_TYPE) {
540 /* Continue with COTP if any data.
541 XXX - if this isn't the first Derived PDU of a segmented Initial
544 if (nsel==NSEL_NET && tvb_get_guint8(next_tvb, 0)==NLPID_ISO10747_IDRP) {
545 if(call_dissector(idrp_handle, next_tvb, pinfo, tree) != 0) {
546 pinfo->fragmented = save_fragmented;
547 return tvb_captured_length(tvb);
550 if (nsel == (guchar)tp_nsap_selector || always_decode_transport) {
551 if (call_dissector(ositp_handle, next_tvb, pinfo, tree) != 0) {
552 pinfo->fragmented = save_fragmented;
553 return tvb_captured_length(tvb); /* yes, it appears to be COTP or CLTP */
556 if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb,
557 pinfo, tree, &hdtbl_entry, NULL)) {
558 pinfo->fragmented = save_fragmented;
559 return tvb_captured_length(tvb); /* yes, it appears to be one of the protocols in the heuristic list */
565 /* The payload is the header and "none, some, or all of the data
566 part of the discarded PDU", i.e. it's like an ICMP error;
567 dissect it as a CLNP PDU. */
569 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
570 next_length = tvb_reported_length_remaining(tvb, offset);
571 if (next_length != 0) {
572 /* We have payload; dissect it. */
573 discpdu_tree = proto_tree_add_subtree(clnp_tree, tvb, offset, next_length,
574 ett_clnp_disc_pdu, NULL, "Discarded PDU");
576 /* Save the current value of the "we're inside an error packet"
577 flag, and set that flag; subdissectors may treat packets
578 that are the payload of error packets differently from
580 save_in_error_pkt = pinfo->flags.in_error_pkt;
581 pinfo->flags.in_error_pkt = TRUE;
583 call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);
585 /* Restore the "we're inside an error packet" flag. */
586 pinfo->flags.in_error_pkt = save_in_error_pkt;
588 pinfo->fragmented = save_fragmented;
589 return tvb_captured_length(tvb); /* we're done with this PDU */
593 /* XXX - dissect this */
597 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
598 call_dissector(data_handle,next_tvb, pinfo, tree);
599 pinfo->fragmented = save_fragmented;
600 return tvb_captured_length(tvb);
604 clnp_reassemble_init(void)
606 reassembly_table_init(&clnp_reassembly_table,
607 &addresses_reassembly_table_functions);
611 clnp_reassemble_cleanup(void)
613 reassembly_table_destroy(&clnp_reassembly_table);
617 proto_register_clnp(void)
619 static hf_register_info hf[] = {
621 { "Network Layer Protocol Identifier", "clnp.nlpi", FT_UINT8, BASE_HEX,
622 VALS(nlpid_vals), 0x0, NULL, HFILL }},
625 { "HDR Length", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
628 { "Version", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
631 { "Holding Time", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
634 { "PDU Type", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
636 { &hf_clnp_cnf_segmentation,
637 { "Segmentation permitted", "clnp.cnf.segmentation", FT_BOOLEAN, 8, TFS(&tfs_yes_no), CNF_SEG_OK, NULL, HFILL }},
639 { &hf_clnp_cnf_more_segments,
640 { "More segments", "clnp.cnf.more_segments", FT_BOOLEAN, 8, TFS(&tfs_yes_no), CNF_MORE_SEGS, NULL, HFILL }},
642 { &hf_clnp_cnf_report_error,
643 { "Report error if PDU discarded", "clnp.cnf.report_error", FT_BOOLEAN, 8, TFS(&tfs_yes_no), CNF_ERR_OK, NULL, HFILL }},
646 { "Type", "clnp.cnf.type", FT_UINT8, BASE_DEC, VALS(npdu_type_vals), CNF_TYPE, NULL, HFILL }},
648 { &hf_clnp_pdu_length,
649 { "PDU length", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
651 { &hf_clnp_data_unit_identifier,
652 { "Data unit identifier", "clnp.data_unit_identifier", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
654 { &hf_clnp_segment_offset,
655 { "Segment offset", "clnp.segment_offset", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
657 { &hf_clnp_total_length,
658 { "Total length", "clnp.total_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
661 { "Checksum", "clnp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
663 { &hf_clnp_dest_length,
664 { "DAL", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
667 { "DA", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
669 { &hf_clnp_src_length,
670 { "SAL", "clnp.ssap.len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
673 { "SA", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
676 { "ATN traffic type", "clnp.atn.tt", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
679 { "ATN security classification", "clnp.atn.sc", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
681 { &hf_clnp_segment_overlap,
682 { "Segment overlap", "clnp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
683 "Segment overlaps with other segments", HFILL }},
685 { &hf_clnp_segment_overlap_conflict,
686 { "Conflicting data in segment overlap", "clnp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
687 "Overlapping segments contained conflicting data", HFILL }},
689 { &hf_clnp_segment_multiple_tails,
690 { "Multiple tail segments found", "clnp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
691 "Several tails were found when reassembling the packet", HFILL }},
693 { &hf_clnp_segment_too_long_segment,
694 { "Segment too long", "clnp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
695 "Segment contained data past end of packet", HFILL }},
697 { &hf_clnp_segment_error,
698 { "Reassembly error", "clnp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
699 "Reassembly error due to illegal segments", HFILL }},
701 { &hf_clnp_segment_count,
702 { "Segment count", "clnp.segment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
706 { "CLNP Segment", "clnp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
710 { "CLNP Segments", "clnp.segments", FT_NONE, BASE_NONE, NULL, 0x0,
713 { &hf_clnp_reassembled_in,
714 { "Reassembled CLNP in frame", "clnp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
715 "This CLNP packet is reassembled in this frame", HFILL }},
717 { &hf_clnp_reassembled_length,
718 { "Reassembled CLNP length", "clnp.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
719 "The total length of the reassembled payload", HFILL }}
721 static gint *ett[] = {
729 static ei_register_info ei[] = {
730 { &ei_clnp_length, { "clnp.len.bad", PI_MALFORMED, PI_ERROR, "Header length value bad", EXPFILL }},
733 module_t *clnp_module;
734 expert_module_t* expert_clnp;
736 proto_clnp = proto_register_protocol(PROTO_STRING_CLNP, "CLNP", "clnp");
737 proto_register_field_array(proto_clnp, hf, array_length(hf));
738 proto_register_subtree_array(ett, array_length(ett));
739 expert_clnp = expert_register_protocol(proto_clnp);
740 expert_register_field_array(expert_clnp, ei, array_length(ei));
741 clnp_handle = register_dissector("clnp", dissect_clnp, proto_clnp);
742 clnp_heur_subdissector_list = register_heur_dissector_list("clnp");
743 register_init_routine(clnp_reassemble_init);
744 register_cleanup_routine(clnp_reassemble_cleanup);
746 register_osi_address_type();
748 clnp_module = prefs_register_protocol(proto_clnp, NULL);
749 prefs_register_uint_preference(clnp_module, "tp_nsap_selector",
750 "NSAP selector for Transport Protocol (last byte in hex)",
751 "NSAP selector for Transport Protocol (last byte in hex)",
752 16, &tp_nsap_selector);
753 prefs_register_bool_preference(clnp_module, "always_decode_transport",
754 "Always try to decode NSDU as transport PDUs",
755 "Always try to decode NSDU as transport PDUs",
756 &always_decode_transport);
757 prefs_register_bool_preference(clnp_module, "reassemble",
758 "Reassemble segmented CLNP datagrams",
759 "Whether segmented CLNP datagrams should be reassembled",
761 prefs_register_bool_preference(clnp_module, "decode_atn_options",
762 "Decode ATN security label",
763 "Whether ATN security label should be decoded",
764 &clnp_decode_atn_options);
768 proto_reg_handoff_clnp(void)
770 ositp_handle = find_dissector("ositp");
771 ositp_inactive_handle = find_dissector("ositp_inactive");
772 idrp_handle = find_dissector("idrp");
773 data_handle = find_dissector("data");
775 dissector_add_uint("osinl.incl", NLPID_ISO8473_CLNP, clnp_handle);
776 dissector_add_uint("osinl.incl", NLPID_NULL, clnp_handle); /* Inactive subset */
777 dissector_add_uint("x.25.spi", NLPID_ISO8473_CLNP, clnp_handle);
781 * Editor modelines - http://www.wireshark.org/tools/modelines.html
786 * indent-tabs-mode: nil
789 * vi: set shiftwidth=4 tabstop=8 expandtab:
790 * :indentSize=4:tabSize=8:noTabs=true: