2 * Routines for ISO/OSI network and transport protocol packet disassembly
3 * Main entrance point and common functions
6 * Laurent Deniel <laurent.deniel@free.fr>
7 * Ralf Schneider <Ralf.Schneider@t-online.de>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include <epan/packet.h>
33 #include <epan/prefs.h>
34 #include <epan/llcsaps.h>
35 #include <epan/aftypes.h>
36 #include <epan/nlpid.h>
37 #include <epan/ppptypes.h>
38 #include <epan/chdlctypes.h>
39 #include <epan/ipproto.h>
40 #include "packet-osi.h"
41 #include "packet-isis.h"
42 #include "packet-esis.h"
43 #include "packet-tpkt.h"
45 static int proto_osi
= -1;
46 static dissector_handle_t osi_handle
;
49 /* Preferences for OSI over TPKT over TCP */
50 static gboolean tpkt_desegment
= FALSE
;
51 static guint global_tcp_port_osi_over_tpkt
= 0;
54 calc_checksum( tvbuff_t
*tvb
, int offset
, guint len
, guint checksum
) {
65 available_len
= tvb_length_remaining( tvb
, offset
);
66 if ( available_len
< len
)
67 return( DATA_MISSING
);
69 buffer
= tvb_get_ptr( tvb
, offset
, len
);
72 * The maximum values of c0 and c1 will occur if all bytes have the
73 * value 255; if so, then c0 will be len*255 and c1 will be
74 * (len*255 + (len-1)*255 + ... + 255), which is
75 * (len + (len - 1) + ... + 1)*255, or 255*(len*(len + 1))/2.
76 * This means it can overflow if "len" is 5804 or greater.
78 * (A+B) mod 255 = ((A mod 255) + (B mod 255) mod 255, so
79 * we can solve this by taking c0 and c1 mod 255 every
89 for (i
= 0; i
< seglen
; i
++) {
99 if (c0
!= 0 || c1
!= 0)
100 return( CKSUM_NOT_OK
); /* XXX - what should the checksum field be? */
107 check_and_get_checksum( tvbuff_t
*tvb
, int offset
, guint len
, guint checksum
, int offset_check
, guint16
* result
) {
112 guint32 c0
, c1
, factor
;
113 guint seglen
, initlen
= len
;
120 available_len
= tvb_length_remaining( tvb
, offset
);
121 offset_check
-= offset
;
122 if ( ( available_len
< len
) || ( offset_check
< 0 ) || ( (guint
)(offset_check
+2) > len
) )
123 return( DATA_MISSING
);
125 buffer
= tvb_get_ptr( tvb
, offset
, len
);
126 block
= offset_check
/ 5803;
129 * The maximum values of c0 and c1 will occur if all bytes have the
130 * value 255; if so, then c0 will be len*255 and c1 will be
131 * (len*255 + (len-1)*255 + ... + 255), which is
132 * (len + (len - 1) + ... + 1)*255, or 255*(len*(len + 1))/2.
133 * This means it can overflow if "len" is 5804 or greater.
135 * (A+B) mod 255 = ((A mod 255) + (B mod 255) mod 255, so
136 * we can solve this by taking c0 and c1 mod 255 every
145 if ( block
-- == 0 ) {
146 seglen
= offset_check
% 5803;
148 } else if ( seglen
> 5803 )
150 for (i
= 0; i
< seglen
; i
++) {
156 * This works even if (offset_check % 5803) == 5802
170 factor
= ( initlen
- offset_check
) * c0
;
171 x
= factor
- c0
- c1
;
175 * This algorithm uses the 8 bits one's complement arithmetic.
176 * Therefore, we must correct an effect produced
177 * by the "standard" arithmetic (two's complement)
186 if (x
== 0) x
= 0xFF;
187 if (y
== 0) y
= 0x01;
189 *result
= ( x
<< 8 ) | ( y
& 0xFF );
191 if (*result
!= checksum
)
192 return( CKSUM_NOT_OK
); /* XXX - what should the checksum field be? */
197 /* 4 octet ATN extended checksum: ICAO doc 9705 Ed3 Volume V section 5.5.4.6.4 */
198 /* It is calculated over TP4 userdata (all checksums set to zero ) and a pseudo tailer */
199 /* of length SRC-NSAP, SRC-NSAP, length DST-NSAP, DST-NSAP and ATN extended checksum. */
200 /* In case of a CR TPDU, the value of the ISO 8073 16-bit fletcher checksum parameter shall */
201 /* be set to zero. */
202 gboolean
check_atn_ec_32(
203 tvbuff_t
*tvb
, guint tpdu_len
,
204 guint offset_ec_32_val
, /* offset ATN extended checksum value, calculated at last as part of pseudo trailer */
205 guint offset_iso8073_val
, /* offset ISO 8073 fletcher checksum, CR only*/
206 guint clnp_dst_len
, /* length of DST-NSAP */
207 const guint8
*clnp_dst
, /* DST-NSAP */
208 guint clnp_src_len
, /* length of SRC-NSAP */
209 const guint8
*clnp_src
) /* SRC-NSAP */
218 /* sum across complete TPDU */
219 for ( i
=0; i
< tpdu_len
; i
++){
220 c0
+= tvb_get_guint8(tvb
, i
) ;
222 if( ( i
>= offset_ec_32_val
) && /* ignore 32 bit ATN extended checksum value */
223 ( i
< ( offset_ec_32_val
+ 4 ) ) ) {
224 c0
-= tvb_get_guint8(tvb
, i
);
227 if( ( offset_iso8073_val
) && /* ignore 16 bit ISO 8073 checksum, if present*/
228 ( i
>= offset_iso8073_val
) &&
229 ( i
< ( offset_iso8073_val
+ 2 ) ) ) {
230 c0
-= tvb_get_guint8(tvb
, i
);
233 if ( c0
>= 0x000000FF )
236 if ( c1
>= 0x000000FF )
239 if ( c2
>= 0x000000FF )
242 if ( c3
>= 0x000000FF )
245 /* add NSAP parts of pseudo trailer */
247 if ( c0
>= 0x000000FF )
250 if ( c1
>= 0x000000FF )
253 if ( c2
>= 0x000000FF )
256 if ( c3
>= 0x000000FF )
258 for ( i
=0; i
< clnp_dst_len
; i
++){
260 if ( c0
>= 0x000000FF )
263 if ( c1
>= 0x000000FF )
266 if ( c2
>= 0x000000FF )
269 if ( c3
>= 0x000000FF )
273 if ( c0
>= 0x000000FF )
276 if ( c1
>= 0x000000FF )
279 if ( c2
>= 0x000000FF )
282 if ( c3
>= 0x000000FF )
284 for ( i
=0; i
< clnp_src_len
; i
++){
286 if ( c0
>= 0x000000FF )
289 if ( c1
>= 0x000000FF )
292 if ( c2
>= 0x000000FF )
295 if ( c3
>= 0x000000FF )
298 /* add extended checksum as last part of the pseudo trailer */
299 for ( i
= offset_ec_32_val
; i
< (offset_ec_32_val
+4); i
++){
300 c0
+= tvb_get_guint8(tvb
, i
) ;
302 if ( c0
>= 0x000000FF )
305 if ( c1
>= 0x000000FF )
308 if ( c2
>= 0x000000FF )
311 if ( c3
>= 0x000000FF )
315 sum
= (c3
<< 24) + (c2
<< 16 ) + (c1
<< 8) + c0
;
323 /* 2 octet ATN extended checksum: ICAO doc 9705 Ed3 Volume V section 5.5.4.6.4 */
324 /* It is calculated over TP4 userdata (all checksums set to zero ) and a pseudo tailer */
325 /* of length SRC-NSAP, SRC-NSAP, length DST-NSAP, DST-NSAP and ATN extended checksum. */
326 /* In case of a CR TPDU, the value of the ISO 8073 16-bit fletcher checksum parameter shall */
327 /* be set to zero. */
328 /* this routine is currently *untested* because of the unavailability of samples.*/
329 gboolean
check_atn_ec_16(
332 guint offset_ec_16_val
, /* offset ATN extended checksum value, calculated at last as part of pseudo trailer */
333 guint offset_iso8073_val
, /* offset ISO 8073 fletcher checksum, CR only*/
334 guint clnp_dst_len
, /* length of DST-NSAP */
335 const guint8
*clnp_dst
, /* DST-NSAP */
336 guint clnp_src_len
, /* length of SRC-NSAP */
337 const guint8
*clnp_src
) /* SRC-NSAP */
344 /* sum across complete TPDU */
345 for ( i
=0; i
< tpdu_len
; i
++){
347 c0
+= tvb_get_guint8(tvb
, i
);
349 if( (i
>= offset_ec_16_val
) && /* ignore 16 bit extended checksum */
350 (i
< (offset_ec_16_val
+ 2) ) ) {
351 c0
-= tvb_get_guint8(tvb
, i
) ;
354 if( (i
>= offset_iso8073_val
) && /* ignore 16 bit ISO 8073 checksum, if present*/
355 (i
< (offset_iso8073_val
+ 2) ) ) {
356 c0
-= tvb_get_guint8(tvb
, i
) ;
365 /* add NSAP parts of pseudo trailer */
372 for ( i
=0; i
< clnp_dst_len
; i
++){
386 for ( i
=0; i
< clnp_src_len
; i
++){
394 /* add extended checksum as last part of the pseudo trailer */
395 for ( i
= offset_ec_16_val
; i
< (offset_ec_16_val
+2); i
++){
396 c0
+= tvb_get_guint8(tvb
, i
) ;
405 sum
= (c1
<< 8) + c0
;
414 /* main entry point */
417 * These assume the NLPID is a secondary protocol identifier, not an
418 * initial protocol identifier.
420 * This is an issue only if, in any packet where an NLPID appears, it's
421 * an initial protocol identifier *AND* it can have the value 1, which
422 * means T.70 for an IPI and X.29 for an SPI.
424 const value_string nlpid_vals
[] = {
425 { NLPID_NULL
, "NULL" },
426 { NLPID_SPI_X_29
, "X.29" },
427 { NLPID_X_633
, "X.633" },
428 { NLPID_Q_931
, "Q.931" },
429 { NLPID_Q_2931
, "Q.2931" },
430 { NLPID_Q_2119
, "Q.2119" },
431 { NLPID_SNAP
, "SNAP" },
432 { NLPID_ISO8473_CLNP
, "CLNP" },
433 { NLPID_ISO9542_ESIS
, "ESIS" },
434 { NLPID_ISO10589_ISIS
, "ISIS" },
435 { NLPID_ISO10747_IDRP
, "IDRP" },
436 { NLPID_ISO9542X25_ESIS
, "ESIS (X.25)" },
437 { NLPID_ISO10030
, "ISO 10030" },
438 { NLPID_ISO11577
, "ISO 11577" },
439 { NLPID_COMPRESSED
, "Data compression protocol" },
441 { NLPID_SNDCF
, "SubNetwork Dependent Convergence Function"},
442 { NLPID_IP6
, "IPv6" },
443 { NLPID_PPP
, "PPP" },
447 static dissector_table_t osinl_incl_subdissector_table
;
448 static dissector_table_t osinl_excl_subdissector_table
;
449 static dissector_handle_t data_handle
, ppp_handle
;
451 /* Dissect OSI over TCP over TPKT */
453 dissect_osi_tpkt(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
455 dissect_tpkt_encap(tvb
, pinfo
, tree
, tpkt_desegment
, osi_handle
);
458 static void dissect_osi(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
463 pinfo
->current_proto
= "OSI";
465 nlpid
= tvb_get_guint8(tvb
, 0);
467 /* try lookup with the subdissector tables that includes the nlpid */
468 if (dissector_try_uint(osinl_incl_subdissector_table
, nlpid
, tvb
, pinfo
, tree
))
470 /* try lookup with the subdissector tables that excludes the nlpid */
471 new_tvb
= tvb_new_subset_remaining(tvb
, 1);
472 if (dissector_try_uint(osinl_excl_subdissector_table
, nlpid
, new_tvb
, pinfo
, tree
))
477 /* ESIS (X.25) is not currently decoded */
479 case NLPID_ISO9542X25_ESIS
:
480 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ESIS (X.25)");
481 call_dissector(data_handle
,tvb
, pinfo
, tree
);
483 case NLPID_ISO10747_IDRP
:
484 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IDRP");
485 call_dissector(data_handle
,tvb
, pinfo
, tree
);
488 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ISO");
489 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Unknown ISO protocol (%02x)", nlpid
);
491 call_dissector(data_handle
,tvb
, pinfo
, tree
);
497 proto_reg_handoff_osi(void)
499 static gboolean osi_prefs_initialized
= FALSE
;
500 static dissector_handle_t osi_tpkt_handle
;
501 static guint tcp_port_osi_over_tpkt
;
503 if (!osi_prefs_initialized
) {
504 osi_handle
= create_dissector_handle(dissect_osi
, proto_osi
);
505 dissector_add_uint("llc.dsap", SAP_OSINL1
, osi_handle
);
506 dissector_add_uint("llc.dsap", SAP_OSINL2
, osi_handle
);
507 dissector_add_uint("llc.dsap", SAP_OSINL3
, osi_handle
);
508 dissector_add_uint("llc.dsap", SAP_OSINL4
, osi_handle
);
509 dissector_add_uint("llc.dsap", SAP_OSINL5
, osi_handle
);
510 dissector_add_uint("ppp.protocol", PPP_OSI
, osi_handle
);
511 dissector_add_uint("chdlc.protocol", CHDLCTYPE_OSI
, osi_handle
);
512 dissector_add_uint("null.type", BSD_AF_ISO
, osi_handle
);
513 dissector_add_uint("gre.proto", SAP_OSINL5
, osi_handle
);
514 dissector_add_uint("ip.proto", IP_PROTO_ISOIP
, osi_handle
); /* ISO-TP4 ISO Transport Protocol Class 4 [RFC905,RC77] */
515 data_handle
= find_dissector("data");
516 ppp_handle
= find_dissector("ppp");
519 osi_tpkt_handle
= create_dissector_handle(dissect_osi_tpkt
, proto_osi
);
520 dissector_add_handle("tcp.port", osi_tpkt_handle
); /* for 'decode-as' */
521 osi_prefs_initialized
= TRUE
;
523 if (tcp_port_osi_over_tpkt
!= 0) {
524 dissector_delete_uint("tcp.port", tcp_port_osi_over_tpkt
, osi_tpkt_handle
);
528 if (global_tcp_port_osi_over_tpkt
!= 0) {
529 dissector_add_uint("tcp.port", global_tcp_port_osi_over_tpkt
, osi_tpkt_handle
);
531 tcp_port_osi_over_tpkt
= global_tcp_port_osi_over_tpkt
;
535 proto_register_osi(void)
537 module_t
*osi_module
;
539 /* There's no "OSI" protocol *per se*, but we do register a
540 dissector table so various protocols running at the
541 network layer can register themselves.
542 all protocols that require inclusion of the NLPID
545 osinl_incl_subdissector_table
= register_dissector_table("osinl.incl",
546 "OSI incl NLPID", FT_UINT8
, BASE_HEX
);
548 /* This dissector table is for those protocols whose PDUs
549 * aren't* defined to begin with an NLPID.
550 * (typically non OSI protocols like IP,IPv6,PPP */
551 osinl_excl_subdissector_table
= register_dissector_table("osinl.excl",
552 "OSI excl NLPID", FT_UINT8
, BASE_HEX
);
554 proto_osi
= proto_register_protocol("OSI", "OSI", "osi");
555 /* Preferences how OSI protocols should be dissected */
556 osi_module
= prefs_register_protocol(proto_osi
, proto_reg_handoff_osi
);
558 prefs_register_uint_preference(osi_module
, "tpkt_port",
559 "TCP port for OSI over TPKT",
560 "TCP port for OSI over TPKT",
561 10, &global_tcp_port_osi_over_tpkt
);
562 prefs_register_bool_preference(osi_module
, "tpkt_reassemble",
563 "Reassemble segmented TPKT datagrams",
564 "Whether segmented TPKT datagrams should be reassembled",