2 * Routines for ISO/OSI network and transport protocol packet disassembly
3 * Main entrance point and common functions
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 * SPDX-License-Identifier: GPL-2.0-or-later
17 #include <epan/packet.h>
18 #include <epan/prefs.h>
19 #include <epan/llcsaps.h>
20 #include <epan/aftypes.h>
21 #include <epan/nlpid.h>
22 #include <epan/ppptypes.h>
23 #include <epan/chdlctypes.h>
24 #include <epan/ipproto.h>
25 #include "packet-osi.h"
26 #include "packet-tpkt.h"
27 #include "packet-juniper.h"
29 void proto_reg_handoff_osi(void);
30 void proto_register_osi(void);
34 static int hf_osi_nlpid
;
36 static dissector_handle_t osi_handle
;
37 static dissector_handle_t osi_tpkt_handle
;
38 static dissector_handle_t osi_juniper_handle
;
41 /* Preferences for OSI over TPKT over TCP */
42 static bool tpkt_desegment
;
45 osi_calc_checksum( tvbuff_t
*tvb
, int offset
, unsigned len
, uint32_t* c0
, uint32_t* c1
) {
46 unsigned available_len
;
51 available_len
= tvb_captured_length_remaining( tvb
, offset
);
52 if ( available_len
< len
)
55 p
= tvb_get_ptr( tvb
, offset
, len
);
58 * The maximum values of c0 and c1 will occur if all bytes have the
59 * value 255; if so, then c0 will be len*255 and c1 will be
60 * (len*255 + (len-1)*255 + ... + 255), which is
61 * (len + (len - 1) + ... + 1)*255, or 255*(len*(len + 1))/2.
62 * This means it can overflow if "len" is 5804 or greater.
64 * (A+B) mod 255 = ((A mod 255) + (B mod 255) mod 255, so
65 * we can solve this by taking c0 and c1 mod 255 every
74 for (i
= 0; i
< seglen
; i
++) {
90 osi_check_and_get_checksum( tvbuff_t
*tvb
, int offset
, unsigned len
, int offset_check
, uint16_t* result
) {
93 uint32_t c0
, c1
, factor
;
94 unsigned seglen
, initlen
= len
;
98 /* Make sure the checksum is part of the data being checksummed. */
99 DISSECTOR_ASSERT(offset_check
>= offset
);
100 DISSECTOR_ASSERT((unsigned)offset_check
+ 2 <= (unsigned)offset
+ len
);
103 * If we don't have all the data to be checksummed, report that and don't
106 if (!tvb_bytes_exist(tvb
, offset
, len
))
108 offset_check
-= offset
;
110 p
= tvb_get_ptr( tvb
, offset
, len
);
111 block
= offset_check
/ 5803;
114 * The maximum values of c0 and c1 will occur if all bytes have the
115 * value 255; if so, then c0 will be len*255 and c1 will be
116 * (len*255 + (len-1)*255 + ... + 255), which is
117 * (len + (len - 1) + ... + 1)*255, or 255*(len*(len + 1))/2.
118 * This means it can overflow if "len" is 5804 or greater.
120 * (A+B) mod 255 = ((A mod 255) + (B mod 255) mod 255, so
121 * we can solve this by taking c0 and c1 mod 255 every
129 if ( block
-- == 0 ) {
130 seglen
= offset_check
% 5803;
132 } else if ( seglen
> 5803 )
134 for (i
= 0; i
< seglen
; i
++) {
140 * This works even if (offset_check % 5803) == 5802
154 factor
= ( initlen
- offset_check
) * c0
;
155 x
= factor
- c0
- c1
;
159 * This algorithm uses the 8 bits one's complement arithmetic.
160 * Therefore, we must correct an effect produced
161 * by the "standard" arithmetic (two's complement)
170 if (x
== 0) x
= 0xFF;
171 if (y
== 0) y
= 0x01;
173 *result
= ( x
<< 8 ) | ( y
& 0xFF );
177 /* 4 octet ATN extended checksum: ICAO doc 9705 Ed3 Volume V section 5.5.4.6.4 */
178 /* It is calculated over TP4 userdata (all checksums set to zero ) and a pseudo tailer */
179 /* of length SRC-NSAP, SRC-NSAP, length DST-NSAP, DST-NSAP and ATN extended checksum. */
180 /* In case of a CR TPDU, the value of the ISO 8073 16-bit fletcher checksum parameter shall */
181 /* be set to zero. */
182 uint32_t check_atn_ec_32(
183 tvbuff_t
*tvb
, unsigned tpdu_len
,
184 unsigned offset_ec_32_val
, /* offset ATN extended checksum value, calculated at last as part of pseudo trailer */
185 unsigned offset_iso8073_val
, /* offset ISO 8073 fletcher checksum, CR only*/
186 unsigned clnp_dst_len
, /* length of DST-NSAP */
187 const uint8_t *clnp_dst
, /* DST-NSAP */
188 unsigned clnp_src_len
, /* length of SRC-NSAP */
189 const uint8_t *clnp_src
) /* SRC-NSAP */
198 /* sum across complete TPDU */
199 for ( i
=0; i
< tpdu_len
; i
++){
200 c0
+= tvb_get_uint8(tvb
, i
) ;
202 if( ( i
>= offset_ec_32_val
) && /* ignore 32 bit ATN extended checksum value */
203 ( i
< ( offset_ec_32_val
+ 4 ) ) ) {
204 c0
-= tvb_get_uint8(tvb
, i
);
207 if( ( offset_iso8073_val
) && /* ignore 16 bit ISO 8073 checksum, if present*/
208 ( i
>= offset_iso8073_val
) &&
209 ( i
< ( offset_iso8073_val
+ 2 ) ) ) {
210 c0
-= tvb_get_uint8(tvb
, i
);
213 if ( c0
>= 0x000000FF )
216 if ( c1
>= 0x000000FF )
219 if ( c2
>= 0x000000FF )
222 if ( c3
>= 0x000000FF )
225 /* add NSAP parts of pseudo trailer */
227 if ( c0
>= 0x000000FF )
230 if ( c1
>= 0x000000FF )
233 if ( c2
>= 0x000000FF )
236 if ( c3
>= 0x000000FF )
238 for ( i
=0; i
< clnp_dst_len
; i
++){
240 if ( c0
>= 0x000000FF )
243 if ( c1
>= 0x000000FF )
246 if ( c2
>= 0x000000FF )
249 if ( c3
>= 0x000000FF )
253 if ( c0
>= 0x000000FF )
256 if ( c1
>= 0x000000FF )
259 if ( c2
>= 0x000000FF )
262 if ( c3
>= 0x000000FF )
264 for ( i
=0; i
< clnp_src_len
; i
++){
266 if ( c0
>= 0x000000FF )
269 if ( c1
>= 0x000000FF )
272 if ( c2
>= 0x000000FF )
275 if ( c3
>= 0x000000FF )
278 /* add extended checksum as last part of the pseudo trailer */
279 for ( i
= offset_ec_32_val
; i
< (offset_ec_32_val
+4); i
++){
280 c0
+= tvb_get_uint8(tvb
, i
) ;
282 if ( c0
>= 0x000000FF )
285 if ( c1
>= 0x000000FF )
288 if ( c2
>= 0x000000FF )
291 if ( c3
>= 0x000000FF )
295 sum
= (c3
<< 24) + (c2
<< 16 ) + (c1
<< 8) + c0
;
299 /* 2 octet ATN extended checksum: ICAO doc 9705 Ed3 Volume V section 5.5.4.6.4 */
300 /* It is calculated over TP4 userdata (all checksums set to zero ) and a pseudo tailer */
301 /* of length SRC-NSAP, SRC-NSAP, length DST-NSAP, DST-NSAP and ATN extended checksum. */
302 /* In case of a CR TPDU, the value of the ISO 8073 16-bit fletcher checksum parameter shall */
303 /* be set to zero. */
304 /* this routine is currently *untested* because of the unavailability of samples.*/
305 uint16_t check_atn_ec_16(
308 unsigned offset_ec_16_val
, /* offset ATN extended checksum value, calculated at last as part of pseudo trailer */
309 unsigned offset_iso8073_val
, /* offset ISO 8073 fletcher checksum, CR only*/
310 unsigned clnp_dst_len
, /* length of DST-NSAP */
311 const uint8_t *clnp_dst
, /* DST-NSAP */
312 unsigned clnp_src_len
, /* length of SRC-NSAP */
313 const uint8_t *clnp_src
) /* SRC-NSAP */
320 /* sum across complete TPDU */
321 for ( i
=0; i
< tpdu_len
; i
++){
323 c0
+= tvb_get_uint8(tvb
, i
);
325 if( (i
>= offset_ec_16_val
) && /* ignore 16 bit extended checksum */
326 (i
< (offset_ec_16_val
+ 2) ) ) {
327 c0
-= tvb_get_uint8(tvb
, i
) ;
330 if( (i
>= offset_iso8073_val
) && /* ignore 16 bit ISO 8073 checksum, if present*/
331 (i
< (offset_iso8073_val
+ 2) ) ) {
332 c0
-= tvb_get_uint8(tvb
, i
) ;
341 /* add NSAP parts of pseudo trailer */
348 for ( i
=0; i
< clnp_dst_len
; i
++){
362 for ( i
=0; i
< clnp_src_len
; i
++){
370 /* add extended checksum as last part of the pseudo trailer */
371 for ( i
= offset_ec_16_val
; i
< (offset_ec_16_val
+2); i
++){
372 c0
+= tvb_get_uint8(tvb
, i
) ;
381 sum
= (c1
<< 8) + c0
;
386 /* main entry point */
389 * These assume the NLPID is a secondary protocol identifier, not an
390 * initial protocol identifier.
392 * This is an issue only if, in any packet where an NLPID appears, it's
393 * an initial protocol identifier *AND* it can have the value 1, which
394 * means T.70 for an IPI and X.29 for an SPI.
396 const value_string nlpid_vals
[] = {
397 { NLPID_NULL
, "NULL" },
398 { NLPID_SPI_X_29
, "X.29" },
399 { NLPID_X_633
, "X.633" },
400 { NLPID_Q_931
, "Q.931" },
401 { NLPID_Q_2931
, "Q.2931" },
402 { NLPID_Q_2119
, "Q.2119" },
403 { NLPID_SNAP
, "SNAP" },
404 { NLPID_ISO8473_CLNP
, "CLNP" },
405 { NLPID_ISO9542_ESIS
, "ESIS" },
406 { NLPID_ISO10589_ISIS
, "ISIS" },
407 { NLPID_ISO10747_IDRP
, "IDRP" },
408 { NLPID_AVAYA_IPVPN
, "Avaya SPBM Fabric IPVPN" },
409 { NLPID_ISO9542X25_ESIS
, "ESIS (X.25)" },
410 { NLPID_ISO10030
, "ISO 10030" },
411 { NLPID_ISO11577
, "ISO 11577" },
412 { NLPID_COMPRESSED
, "Data compression protocol" },
414 { NLPID_TRILL
, "TRILL" },
415 { NLPID_SNDCF
, "SubNetwork Dependent Convergence Function"},
416 { NLPID_IP6
, "IPv6" },
417 { NLPID_PPP
, "PPP" },
421 static dissector_table_t osinl_incl_subdissector_table
;
422 static dissector_table_t osinl_excl_subdissector_table
;
423 static dissector_handle_t ppp_handle
;
425 /* Dissect OSI over TCP over TPKT */
427 dissect_osi_tpkt(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
429 dissect_tpkt_encap(tvb
, pinfo
, tree
, tpkt_desegment
, osi_handle
);
430 return tvb_captured_length(tvb
);
433 static int dissect_osi_juniper(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
438 nlpid
= tvb_get_uint8(tvb
, 0);
439 if(dissector_try_uint(osinl_incl_subdissector_table
, nlpid
, tvb
, pinfo
, tree
))
440 return tvb_captured_length(tvb
);
442 next_tvb
= tvb_new_subset_remaining(tvb
, 1);
443 dissector_try_uint(osinl_excl_subdissector_table
, nlpid
, next_tvb
, pinfo
, tree
);
444 return tvb_captured_length(tvb
);
447 static int dissect_osi(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
452 nlpid
= tvb_get_uint8(tvb
, 0);
455 * Try the subdissector table for protocols in which the NLPID is
456 * considered part of the PDU; it should be handed a tvbuff that
457 * includes the NLPID, and should put the NLPID into the protocol
460 if (dissector_try_uint(osinl_incl_subdissector_table
, nlpid
, tvb
, pinfo
, tree
))
461 return tvb_captured_length(tvb
);
464 * Try the subdissector table for protocols in which the NLPID is
465 * *not* considered part of the PDU; it should be handed a tvbuff
466 * that doesn't include the NLPID, and we should put the NLPID into
467 * the protocol tree ourselves.
469 proto_tree_add_uint(tree
, hf_osi_nlpid
, tvb
, 0, 1, nlpid
);
470 new_tvb
= tvb_new_subset_remaining(tvb
, 1);
471 if (dissector_try_uint(osinl_excl_subdissector_table
, nlpid
, new_tvb
, pinfo
, tree
))
472 return tvb_captured_length(tvb
);
476 /* ESIS (X.25) is not currently decoded */
478 case NLPID_ISO9542X25_ESIS
:
479 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ESIS (X.25)");
480 call_data_dissector(tvb
, pinfo
, tree
);
482 case NLPID_ISO10747_IDRP
:
483 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IDRP");
484 call_data_dissector(tvb
, pinfo
, tree
);
487 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ISO");
488 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Unknown ISO protocol (%02x)", nlpid
);
490 call_data_dissector(tvb
, pinfo
, tree
);
493 return tvb_captured_length(tvb
);
497 proto_reg_handoff_osi(void)
499 dissector_add_uint("llc.dsap", SAP_OSINL1
, osi_handle
);
500 dissector_add_uint("llc.dsap", SAP_OSINL2
, osi_handle
);
501 dissector_add_uint("llc.dsap", SAP_OSINL3
, osi_handle
);
502 dissector_add_uint("llc.dsap", SAP_OSINL4
, osi_handle
);
503 dissector_add_uint("llc.dsap", SAP_OSINL5
, osi_handle
);
504 dissector_add_uint("ppp.protocol", PPP_OSI
, osi_handle
);
505 dissector_add_uint("chdlc.protocol", CHDLCTYPE_OSI
, osi_handle
);
506 dissector_add_uint("null.type", BSD_AF_ISO
, osi_handle
);
507 dissector_add_uint("gre.proto", SAP_OSINL5
, osi_handle
);
508 dissector_add_uint("ip.proto", IP_PROTO_ISOIP
, osi_handle
); /* ISO network layer PDUs [RFC 1070] */
510 dissector_add_uint("juniper.proto", JUNIPER_PROTO_ISO
, osi_juniper_handle
);
511 dissector_add_uint("juniper.proto", JUNIPER_PROTO_CLNP
, osi_juniper_handle
);
512 dissector_add_uint("juniper.proto", JUNIPER_PROTO_MPLS_CLNP
, osi_juniper_handle
);
514 ppp_handle
= find_dissector("ppp");
516 dissector_add_for_decode_as_with_preference("tcp.port", osi_tpkt_handle
);
520 proto_register_osi(void)
522 static hf_register_info hf
[] = {
524 { "Network Layer Protocol Identifier", "osi.nlpid", FT_UINT8
, BASE_HEX
,
525 VALS(nlpid_vals
), 0x0, NULL
, HFILL
}},
527 module_t
*osi_module
;
529 proto_osi
= proto_register_protocol("OSI", "OSI", "osi");
530 proto_register_field_array(proto_osi
, hf
, array_length(hf
));
532 /* There's no "OSI" protocol *per se*, but we do register a
533 dissector table so various protocols running at the
534 network layer can register themselves.
535 all protocols that require inclusion of the NLPID
538 osinl_incl_subdissector_table
= register_dissector_table("osinl.incl",
539 "OSI incl NLPID", proto_osi
, FT_UINT8
, BASE_HEX
);
541 /* This dissector table is for those protocols whose PDUs
542 * aren't* defined to begin with an NLPID.
543 * (typically non OSI protocols like IP,IPv6,PPP */
544 osinl_excl_subdissector_table
= register_dissector_table("osinl.excl",
545 "OSI excl NLPID", proto_osi
, FT_UINT8
, BASE_HEX
);
547 /* Preferences how OSI protocols should be dissected */
548 osi_module
= prefs_register_protocol(proto_osi
, NULL
);
550 prefs_register_bool_preference(osi_module
, "tpkt_reassemble",
551 "Reassemble segmented TPKT datagrams",
552 "Whether segmented TPKT datagrams should be reassembled",
555 /* Register the dissector handles */
556 osi_handle
= register_dissector("osi", dissect_osi
, proto_osi
);
557 osi_juniper_handle
= register_dissector("osi_juniper", dissect_osi_juniper
, proto_osi
);
558 osi_tpkt_handle
= register_dissector("osi_tpkt", dissect_osi_tpkt
, proto_osi
);
562 * Editor modelines - https://www.wireshark.org/tools/modelines.html
567 * indent-tabs-mode: nil
570 * ex: set shiftwidth=2 tabstop=8 expandtab:
571 * :indentSize=2:tabSize=8:noTabs=true: