MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-clnp.c
blob800b28e31ae572c50986df75b4abfa0ff0ff29a1
1 /* packet-clnp.c
2 * Routines for ISO/OSI network protocol packet disassembly
4 * $Id$
5 * Laurent Deniel <laurent.deniel@free.fr>
6 * Ralf Schneider <Ralf.Schneider@t-online.de>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "config.h"
29 #include <glib.h>
31 #include <epan/packet.h>
32 #include <epan/prefs.h>
33 #include <epan/reassemble.h>
34 #include <epan/expert.h>
35 #include <epan/nlpid.h>
36 #include <epan/ipproto.h>
38 #include "packet-osi.h"
39 #include "packet-osi-options.h"
40 #include "packet-isis.h"
41 #include "packet-esis.h"
43 void proto_register_clnp(void);
44 void proto_reg_handoff_clnp(void);
46 /* protocols and fields */
48 static int proto_clnp = -1;
49 static gint ett_clnp = -1;
50 static gint ett_clnp_type = -1;
51 static gint ett_clnp_segments = -1;
52 static gint ett_clnp_segment = -1;
53 static gint ett_clnp_disc_pdu = -1;
55 static int hf_clnp_id = -1;
56 static int hf_clnp_length = -1;
57 static int hf_clnp_version = -1;
58 static int hf_clnp_ttl = -1;
59 static int hf_clnp_type = -1;
60 static int hf_clnp_cnf_segmentation = -1;
61 static int hf_clnp_cnf_more_segments = -1;
62 static int hf_clnp_cnf_report_error = -1;
63 static int hf_clnp_cnf_type = -1;
64 static int hf_clnp_pdu_length = -1;
65 static int hf_clnp_checksum = -1;
66 static int hf_clnp_dest_length = -1;
67 static int hf_clnp_dest = -1;
68 static int hf_clnp_src_length = -1;
69 static int hf_clnp_src = -1;
70 int hf_clnp_atntt = -1; /* as referenced in packet-osi-options.c */
71 int hf_clnp_atnsc = -1; /* as referenced in packet-osi-options.c */
72 static int hf_clnp_segments = -1;
73 static int hf_clnp_segment = -1;
74 static int hf_clnp_segment_overlap = -1;
75 static int hf_clnp_segment_overlap_conflict = -1;
76 static int hf_clnp_segment_multiple_tails = -1;
77 static int hf_clnp_segment_too_long_segment = -1;
78 static int hf_clnp_segment_error = -1;
79 static int hf_clnp_segment_count = -1;
80 static int hf_clnp_reassembled_in = -1;
81 static int hf_clnp_reassembled_length = -1;
83 static const fragment_items clnp_frag_items = {
84 &ett_clnp_segment,
85 &ett_clnp_segments,
86 &hf_clnp_segments,
87 &hf_clnp_segment,
88 &hf_clnp_segment_overlap,
89 &hf_clnp_segment_overlap_conflict,
90 &hf_clnp_segment_multiple_tails,
91 &hf_clnp_segment_too_long_segment,
92 &hf_clnp_segment_error,
93 &hf_clnp_segment_count,
94 &hf_clnp_reassembled_in,
95 &hf_clnp_reassembled_length,
96 /* Reassembled data field */
97 NULL,
98 "segments"
101 static expert_field ei_clnp_length = EI_INIT;
103 static dissector_handle_t clnp_handle;
104 static dissector_handle_t ositp_handle;
105 static dissector_handle_t ositp_inactive_handle;
106 static dissector_handle_t idrp_handle;
107 static dissector_handle_t data_handle;
110 * ISO 8473 OSI CLNP definition (see RFC994)
112 * _________________________________
113 * | Fixed Part |
114 * |_________________________________|
115 * | Address Part |
116 * |_________________________________|
117 * | Segmentation Part (optional) |
118 * |_________________________________|
119 * | Options Part (optional) |
120 * |_________________________________|
121 * | Data (optional) |
122 * |_________________________________|
125 #define ISO8473_V1 0x01 /* CLNP version 1 */
127 /* Fixed part */
129 /* Length of fixed part */
130 #define FIXED_PART_LEN 9
132 #define CNF_TYPE 0x1f
133 #define CNF_ERR_OK 0x20
134 #define CNF_MORE_SEGS 0x40
135 #define CNF_SEG_OK 0x80
137 #define DT_NPDU 0x1C
138 #define MD_NPDU 0x1D
139 #define ER_NPDU 0x01
140 #define ERQ_NPDU 0x1E
141 #define ERP_NPDU 0x1F
143 static const value_string npdu_type_abbrev_vals[] = {
144 { DT_NPDU, "DT" },
145 { MD_NPDU, "MD" },
146 { ER_NPDU, "ER" },
147 { ERQ_NPDU, "ERQ" },
148 { ERP_NPDU, "ERP" },
149 { 0, NULL }
152 static const value_string npdu_type_vals[] = {
153 { DT_NPDU, "Data" },
154 { MD_NPDU, "Multicast Data" },
155 { ER_NPDU, "Error Report" },
156 { ERQ_NPDU, "Echo Request" },
157 { ERP_NPDU, "Echo Response" },
158 { 0, NULL }
161 /* field position */
163 #define P_CLNP_PROTO_ID 0
164 #define P_CLNP_HDR_LEN 1
165 #define P_CLNP_VERS 2
166 #define P_CLNP_TTL 3
167 #define P_CLNP_TYPE 4
168 #define P_CLNP_SEGLEN 5
169 #define P_CLNP_CKSUM 7
170 #define P_CLNP_ADDRESS_PART 9
172 /* Segmentation part */
174 #define SEGMENTATION_PART_LEN 6
176 struct clnp_segment {
177 gushort cng_id; /* data unit identifier */
178 gushort cng_off; /* segment offset */
179 gushort cng_tot_len; /* total length */
182 /* NSAP selector */
184 #define NSEL_NET 0x00
185 #define NSEL_NP 0x20
186 #define NSEL_TP 0x21
188 /* global variables */
190 /* List of dissectors to call for CLNP packets */
191 static heur_dissector_list_t clnp_heur_subdissector_list;
194 * Reassembly of CLNP.
196 static reassembly_table clnp_reassembly_table;
198 /* options */
199 static guint tp_nsap_selector = NSEL_TP;
200 static gboolean always_decode_transport = FALSE;
201 static gboolean clnp_reassemble = TRUE;
202 gboolean clnp_decode_atn_options = FALSE;
204 /* function definitions */
207 * CLNP part / main entry point
210 static void
211 dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
213 proto_tree *clnp_tree;
214 proto_item *ti, *ti_len = NULL, *ti_pdu_len = NULL, *ti_tot_len = NULL;
215 guint8 cnf_proto_id;
216 guint8 cnf_hdr_len;
217 guint8 cnf_vers;
218 guint8 cnf_ttl;
219 guint8 cnf_type;
220 char flag_string[6+1];
221 const char *pdu_type_string;
222 proto_tree *type_tree;
223 guint16 segment_length;
224 guint16 du_id = 0;
225 guint16 segment_offset = 0;
226 guint16 total_length;
227 guint16 cnf_cksum;
228 cksum_status_t cksum_status;
229 int offset;
230 guchar src_len, dst_len, nsel, opt_len = 0;
231 const guint8 *dst_addr, *src_addr;
232 guint next_length;
233 proto_tree *discpdu_tree;
234 gboolean save_in_error_pkt;
235 fragment_head *fd_head;
236 tvbuff_t *next_tvb;
237 gboolean update_col_info = TRUE;
238 gboolean save_fragmented;
240 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CLNP");
241 col_clear(pinfo->cinfo, COL_INFO);
243 cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID);
244 if (cnf_proto_id == NLPID_NULL) {
245 col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset");
246 ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, ENC_NA);
247 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
248 proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
249 cnf_proto_id, "Inactive subset");
250 next_tvb = tvb_new_subset_remaining(tvb, 1);
251 if (call_dissector(ositp_inactive_handle, next_tvb, pinfo, tree) == 0)
252 call_dissector(data_handle,tvb, pinfo, tree);
253 return;
256 /* return if version not known */
257 cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS);
258 if (cnf_vers != ISO8473_V1) {
259 call_dissector(data_handle,tvb, pinfo, tree);
260 return;
263 /* fixed part decoding */
264 cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
266 ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA);
267 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
268 proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
269 cnf_proto_id);
270 ti_len = proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
271 cnf_hdr_len);
272 if (cnf_hdr_len < FIXED_PART_LEN) {
273 /* Header length is less than the length of the fixed part of
274 the header. */
275 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
276 "Header length value < minimum length %u",
277 FIXED_PART_LEN);
278 return;
280 proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
281 cnf_vers);
282 cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
283 proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
284 cnf_ttl,
285 "Holding Time : %u (%u.%u secs)",
286 cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
287 cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
288 pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
289 "Unknown (0x%02x)");
290 flag_string[0] = '\0';
291 if (cnf_type & CNF_SEG_OK)
292 g_strlcat(flag_string, "S ", 7);
293 if (cnf_type & CNF_MORE_SEGS)
294 g_strlcat(flag_string, "M ", 7);
295 if (cnf_type & CNF_ERR_OK)
296 g_strlcat(flag_string, "E ", 7);
297 ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
298 cnf_type,
299 "PDU Type : 0x%02x (%s%s)",
300 cnf_type,
301 flag_string,
302 pdu_type_string);
303 type_tree = proto_item_add_subtree(ti, ett_clnp_type);
304 proto_tree_add_item(type_tree, hf_clnp_cnf_segmentation, tvb, P_CLNP_TYPE, 1, ENC_NA);
305 proto_tree_add_item(type_tree, hf_clnp_cnf_more_segments, tvb, P_CLNP_TYPE, 1, ENC_NA);
306 proto_tree_add_item(type_tree, hf_clnp_cnf_report_error, tvb, P_CLNP_TYPE, 1, ENC_NA);
307 proto_tree_add_item(type_tree, hf_clnp_cnf_type, tvb, P_CLNP_TYPE, 1, ENC_NA);
309 /* If we don't have the full header - i.e., not enough to see the
310 segmentation part and determine whether this datagram is segmented
311 or not - set the Info column now; we'll get an exception before
312 we set it otherwise. */
314 if (tvb_length(tvb) < cnf_hdr_len) {
315 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
318 segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
319 ti_pdu_len = proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
320 segment_length);
321 if (segment_length < cnf_hdr_len) {
322 /* Segment length is less than the header length. */
323 expert_add_info_format(pinfo, ti_pdu_len, &ei_clnp_length,
324 "PDU length < header length %u", cnf_hdr_len);
325 return;
327 cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
328 cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum);
329 switch (cksum_status) {
330 default:
332 * No checksum present, or not enough of the header present to
333 * checksum it.
335 proto_tree_add_uint(clnp_tree, hf_clnp_checksum, tvb,
336 P_CLNP_CKSUM, 2,
337 cnf_cksum);
338 break;
340 case CKSUM_OK:
342 * Checksum is correct.
344 proto_tree_add_uint_format_value(clnp_tree, hf_clnp_checksum, tvb,
345 P_CLNP_CKSUM, 2,
346 cnf_cksum,
347 "0x%04x (correct)",
348 cnf_cksum);
349 break;
351 case CKSUM_NOT_OK:
353 * Checksum is not correct.
355 proto_tree_add_uint_format_value(clnp_tree, hf_clnp_checksum, tvb,
356 P_CLNP_CKSUM, 2,
357 cnf_cksum,
358 "0x%04x (incorrect)",
359 cnf_cksum);
360 break;
363 opt_len = cnf_hdr_len;
364 opt_len -= FIXED_PART_LEN; /* Fixed part of Header */
366 /* address part */
368 offset = P_CLNP_ADDRESS_PART;
369 if (opt_len < 1) {
370 /* Header length is less than the minimum value in CLNP,
371 including the destination address length. */
372 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
373 "Header length value < %u",
374 FIXED_PART_LEN + 1);
375 return;
377 dst_len = tvb_get_guint8(tvb, offset);
378 if (tree) {
379 proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
380 dst_len);
382 offset += 1;
383 opt_len -= 1;
385 if (opt_len < dst_len) {
386 /* Header length is less than the minimum value,
387 including the destination address length and the
388 destination address. */
389 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
390 "Header length value < %u",
391 FIXED_PART_LEN + 1 + dst_len);
392 return;
394 dst_addr = tvb_get_ptr(tvb, offset, dst_len);
395 nsel = tvb_get_guint8(tvb, offset + dst_len - 1);
396 SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr);
397 SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr);
398 proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_dest, tvb, offset, dst_len,
399 dst_addr,
400 "%s",
401 print_nsap_net(dst_addr, dst_len));
402 offset += dst_len;
403 opt_len -= dst_len;
405 if (opt_len < 1) {
406 /* Header length is less than the minimum value,
407 including the destination address length, the
408 destination address, and the source address length. */
409 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
410 "Header length value < %u",
411 FIXED_PART_LEN + 1 + dst_len + 1);
412 return;
414 src_len = tvb_get_guint8(tvb, offset);
415 if (tree) {
416 proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
417 offset, 1, src_len);
419 offset += 1;
420 opt_len -= 1;
422 if (opt_len < src_len) {
423 /* Header length is less than the minimum value,
424 including the destination address length, the
425 destination address, the source address length,
426 and the source address. */
427 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
428 "Header length value < %u",
429 FIXED_PART_LEN + 1 + dst_len + 1 + src_len);
430 return;
432 src_addr = tvb_get_ptr(tvb, offset, src_len);
433 SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr);
434 SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr);
435 proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_src, tvb,
436 offset, src_len,
437 src_addr,
438 "%s",
439 print_nsap_net(src_addr, src_len));
441 offset += src_len;
442 opt_len -= src_len;
444 /* Segmentation Part */
446 if (cnf_type & CNF_SEG_OK) {
447 if (opt_len < SEGMENTATION_PART_LEN) {
448 /* Header length is less than the minimum value,
449 including the destination address length, the
450 destination address, the source address length,
451 the source address, and the segmentation part. */
452 expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
453 "Header length value < %u",
454 FIXED_PART_LEN + 1 + dst_len + 1 + SEGMENTATION_PART_LEN);
455 return;
457 du_id = tvb_get_ntohs(tvb, offset);
458 proto_tree_add_text(clnp_tree, tvb, offset, 2,
459 "Data unit identifier: %06u",
460 du_id);
461 segment_offset = tvb_get_ntohs(tvb, offset + 2);
462 proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2,
463 "Segment offset : %6u",
464 segment_offset);
465 total_length = tvb_get_ntohs(tvb, offset + 4);
466 ti_tot_len = proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2,
467 "Total length : %6u",
468 total_length);
469 if (total_length < segment_length) {
470 /* Reassembled length is less than the length of this segment. */
471 expert_add_info_format(pinfo, ti_tot_len, &ei_clnp_length,
472 "Total length < segment length %u", segment_length);
473 return;
475 offset += SEGMENTATION_PART_LEN;
476 opt_len -= SEGMENTATION_PART_LEN;
479 dissect_osi_options(opt_len, tvb, offset, clnp_tree);
481 offset += opt_len;
483 /* If clnp_reassemble is on, this is a segment, we have all the
484 * data in the segment, and the checksum is valid, then just add the
485 * segment to the hashtable.
487 save_fragmented = pinfo->fragmented;
488 if (clnp_reassemble && (cnf_type & CNF_SEG_OK) &&
489 ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) &&
490 tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) &&
491 segment_length > cnf_hdr_len &&
492 cksum_status != CKSUM_NOT_OK) {
493 fd_head = fragment_add_check(&clnp_reassembly_table,
494 tvb, offset, pinfo, du_id, NULL,
495 segment_offset, segment_length - cnf_hdr_len,
496 cnf_type & CNF_MORE_SEGS);
498 next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP",
499 fd_head, &clnp_frag_items, &update_col_info, clnp_tree);
500 } else {
501 /* If this is the first segment, dissect its contents, otherwise
502 just show it as a segment.
504 XXX - if we eventually don't save the reassembled contents of all
505 segmented datagrams, we may want to always reassemble. */
506 if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) {
507 /* Not the first segment - don't dissect it. */
508 next_tvb = NULL;
509 } else {
510 /* First segment, or not segmented. Dissect what we have here. */
512 /* Get a tvbuff for the payload. Set its length to the segment
513 length, and flag it as a fragment, so going past the end
514 reports FragmentBoundsError, i.e. "there's data missing
515 because this isn't reassembled", not ReportedBoundsError,
516 i.e. "the dissector ran past the end of the packet, so the
517 packet must not have been constructed properly". */
518 next_tvb = tvb_new_subset_length(tvb, offset, segment_length - cnf_hdr_len);
519 tvb_set_fragment(next_tvb);
522 * If this is the first segment, but not the only segment,
523 * tell the next protocol that.
525 if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS))
526 pinfo->fragmented = TRUE;
527 else
528 pinfo->fragmented = FALSE;
532 if (next_tvb == NULL) {
533 /* Just show this as a segment. */
534 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
535 pdu_type_string, flag_string, segment_offset);
537 /* As we haven't reassembled anything, we haven't changed "pi", so
538 we don't have to restore it. */
539 call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo,
540 tree);
541 pinfo->fragmented = save_fragmented;
542 return;
545 if (tvb_offset_exists(tvb, offset)) {
546 switch (cnf_type & CNF_TYPE) {
548 case DT_NPDU:
549 case MD_NPDU:
550 /* Continue with COTP if any data.
551 XXX - if this isn't the first Derived PDU of a segmented Initial
552 PDU, skip that? */
554 if (nsel==NSEL_NET && tvb_get_guint8(next_tvb, 0)==NLPID_ISO10747_IDRP) {
555 if(call_dissector(idrp_handle, next_tvb, pinfo, tree) != 0) {
556 pinfo->fragmented = save_fragmented;
557 return;
560 if (nsel == (guchar)tp_nsap_selector || always_decode_transport) {
561 if (call_dissector(ositp_handle, next_tvb, pinfo, tree) != 0) {
562 pinfo->fragmented = save_fragmented;
563 return; /* yes, it appears to be COTP or CLTP */
566 if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb,
567 pinfo, tree, NULL)) {
568 pinfo->fragmented = save_fragmented;
569 return; /* yes, it appears to be one of the protocols in the heuristic list */
572 break;
574 case ER_NPDU:
575 /* The payload is the header and "none, some, or all of the data
576 part of the discarded PDU", i.e. it's like an ICMP error;
577 dissect it as a CLNP PDU. */
579 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
580 next_length = tvb_length_remaining(tvb, offset);
581 if (next_length != 0) {
582 /* We have payload; dissect it. */
583 ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length,
584 "Discarded PDU");
585 discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu);
587 /* Save the current value of the "we're inside an error packet"
588 flag, and set that flag; subdissectors may treat packets
589 that are the payload of error packets differently from
590 "real" packets. */
591 save_in_error_pkt = pinfo->flags.in_error_pkt;
592 pinfo->flags.in_error_pkt = TRUE;
594 call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);
596 /* Restore the "we're inside an error packet" flag. */
597 pinfo->flags.in_error_pkt = save_in_error_pkt;
599 pinfo->fragmented = save_fragmented;
600 return; /* we're done with this PDU */
602 case ERQ_NPDU:
603 case ERP_NPDU:
604 /* XXX - dissect this */
605 break;
608 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
609 call_dissector(data_handle,next_tvb, pinfo, tree);
610 pinfo->fragmented = save_fragmented;
611 } /* dissect_clnp */
613 static void
614 clnp_reassemble_init(void)
616 reassembly_table_init(&clnp_reassembly_table,
617 &addresses_reassembly_table_functions);
620 void
621 proto_register_clnp(void)
623 static hf_register_info hf[] = {
624 { &hf_clnp_id,
625 { "Network Layer Protocol Identifier", "clnp.nlpi", FT_UINT8, BASE_HEX,
626 VALS(nlpid_vals), 0x0, NULL, HFILL }},
628 { &hf_clnp_length,
629 { "HDR Length", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
631 { &hf_clnp_version,
632 { "Version", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
634 { &hf_clnp_ttl,
635 { "Holding Time", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
637 { &hf_clnp_type,
638 { "PDU Type", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
640 { &hf_clnp_cnf_segmentation,
641 { "Segmentation permitted", "clnp.cnf.segmentation", FT_BOOLEAN, 8, TFS(&tfs_yes_no), CNF_SEG_OK, NULL, HFILL }},
643 { &hf_clnp_cnf_more_segments,
644 { "More segments", "clnp.cnf.more_segments", FT_BOOLEAN, 8, TFS(&tfs_yes_no), CNF_MORE_SEGS, NULL, HFILL }},
646 { &hf_clnp_cnf_report_error,
647 { "Report error if PDU discarded", "clnp.cnf.report_error", FT_BOOLEAN, 8, TFS(&tfs_yes_no), CNF_ERR_OK, NULL, HFILL }},
649 { &hf_clnp_cnf_type,
650 { "Type", "clnp.cnf.type", FT_UINT8, BASE_DEC, VALS(npdu_type_vals), CNF_TYPE, NULL, HFILL }},
652 { &hf_clnp_pdu_length,
653 { "PDU length", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
655 { &hf_clnp_checksum,
656 { "Checksum", "clnp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
658 { &hf_clnp_dest_length,
659 { "DAL", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
661 { &hf_clnp_dest,
662 { "DA", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
664 { &hf_clnp_src_length,
665 { "SAL", "clnp.ssap.len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
667 { &hf_clnp_src,
668 { "SA", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
670 { &hf_clnp_atntt,
671 { "ATN traffic type", "clnp.atn.tt", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
673 { &hf_clnp_atnsc,
674 { "ATN security classification", "clnp.atn.sc", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
676 { &hf_clnp_segment_overlap,
677 { "Segment overlap", "clnp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
678 "Segment overlaps with other segments", HFILL }},
680 { &hf_clnp_segment_overlap_conflict,
681 { "Conflicting data in segment overlap", "clnp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
682 "Overlapping segments contained conflicting data", HFILL }},
684 { &hf_clnp_segment_multiple_tails,
685 { "Multiple tail segments found", "clnp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
686 "Several tails were found when reassembling the packet", HFILL }},
688 { &hf_clnp_segment_too_long_segment,
689 { "Segment too long", "clnp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
690 "Segment contained data past end of packet", HFILL }},
692 { &hf_clnp_segment_error,
693 { "Reassembly error", "clnp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
694 "Reassembly error due to illegal segments", HFILL }},
696 { &hf_clnp_segment_count,
697 { "Segment count", "clnp.segment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
698 NULL, HFILL }},
700 { &hf_clnp_segment,
701 { "CLNP Segment", "clnp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
702 NULL, HFILL }},
704 { &hf_clnp_segments,
705 { "CLNP Segments", "clnp.segments", FT_NONE, BASE_NONE, NULL, 0x0,
706 NULL, HFILL }},
708 { &hf_clnp_reassembled_in,
709 { "Reassembled CLNP in frame", "clnp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
710 "This CLNP packet is reassembled in this frame", HFILL }},
712 { &hf_clnp_reassembled_length,
713 { "Reassembled CLNP length", "clnp.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
714 "The total length of the reassembled payload", HFILL }}
716 static gint *ett[] = {
717 &ett_clnp,
718 &ett_clnp_type,
719 &ett_clnp_segments,
720 &ett_clnp_segment,
721 &ett_clnp_disc_pdu,
724 static ei_register_info ei[] = {
725 { &ei_clnp_length, { "clnp.len.bad", PI_MALFORMED, PI_ERROR, "Header length value bad", EXPFILL }},
728 module_t *clnp_module;
729 expert_module_t* expert_clnp;
731 proto_clnp = proto_register_protocol(PROTO_STRING_CLNP, "CLNP", "clnp");
732 proto_register_field_array(proto_clnp, hf, array_length(hf));
733 proto_register_subtree_array(ett, array_length(ett));
734 expert_clnp = expert_register_protocol(proto_clnp);
735 expert_register_field_array(expert_clnp, ei, array_length(ei));
736 register_dissector("clnp", dissect_clnp, proto_clnp);
737 register_heur_dissector_list("clnp", &clnp_heur_subdissector_list);
738 register_init_routine(clnp_reassemble_init);
740 clnp_module = prefs_register_protocol(proto_clnp, NULL);
741 prefs_register_uint_preference(clnp_module, "tp_nsap_selector",
742 "NSAP selector for Transport Protocol (last byte in hex)",
743 "NSAP selector for Transport Protocol (last byte in hex)",
744 16, &tp_nsap_selector);
745 prefs_register_bool_preference(clnp_module, "always_decode_transport",
746 "Always try to decode NSDU as transport PDUs",
747 "Always try to decode NSDU as transport PDUs",
748 &always_decode_transport);
749 prefs_register_bool_preference(clnp_module, "reassemble",
750 "Reassemble segmented CLNP datagrams",
751 "Whether segmented CLNP datagrams should be reassembled",
752 &clnp_reassemble);
753 prefs_register_bool_preference(clnp_module, "decode_atn_options",
754 "Decode ATN security label",
755 "Whether ATN security label should be decoded",
756 &clnp_decode_atn_options);
759 void
760 proto_reg_handoff_clnp(void)
762 ositp_handle = find_dissector("ositp");
763 ositp_inactive_handle = find_dissector("ositp_inactive");
764 idrp_handle = find_dissector("idrp");
765 data_handle = find_dissector("data");
767 clnp_handle = create_dissector_handle(dissect_clnp, proto_clnp);
768 dissector_add_uint("osinl.incl", NLPID_ISO8473_CLNP, clnp_handle);
769 dissector_add_uint("osinl.incl", NLPID_NULL, clnp_handle); /* Inactive subset */
770 dissector_add_uint("x.25.spi", NLPID_ISO8473_CLNP, clnp_handle);
774 * Editor modelines - http://www.wireshark.org/tools/modelines.html
776 * Local variables:
777 * c-basic-offset: 4
778 * tab-width: 8
779 * indent-tabs-mode: nil
780 * End:
782 * vi: set shiftwidth=4 tabstop=8 expandtab:
783 * :indentSize=4:tabSize=8:noTabs=true: