From guettler:

ATN decoding fixes for CLNP and COTP dissectors (configurable by option).

ATN decoding fixes for CLNP and COTP dissectors (configurable by option).

ATN specifics may be
selected/deseleted per CLNP/COTP dissector configuration (as requested).

CLNP dissector
1) configurable decoding of "ATN security label"

COTP dissector
1) configurable decoding of ATN TPDU's 
2) checksum calculation (none,OSI,ATN 16-bit, ATN 32-bit)
3) VP decoding for DR TPDU's

https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5622

svn path=/trunk/; revision=46043
This commit is contained in:
Anders Broman 2012-11-16 14:18:27 +00:00
parent 22d1aa1f6c
commit c6cf5703f5
5 changed files with 977 additions and 155 deletions

View File

@ -38,6 +38,12 @@
#include <epan/nlpid.h>
#include <epan/ipproto.h>
/* pseudo-trailer for ATN extended checksums on TP4 layer*/
/* the checksum is calculated from the TPDU as well als */
/* dst NSAP length, dst NSAP, src NSAP length and src NSAP as encoded in CLNP PDU*/
guint clnp_pt_len ;
guint8 clnp_pt_buffer[42];
/* protocols and fields */
static int proto_clnp = -1;
@ -62,6 +68,8 @@ static int hf_clnp_dest_length = -1;
static int hf_clnp_dest = -1;
static int hf_clnp_src_length = -1;
static int hf_clnp_src = -1;
int hf_clnp_atntt = -1; /* as referenced in packet-osi-options.c */
int hf_clnp_atnsc = -1; /* as referenced in packet-osi-options.c */
static int hf_clnp_segments = -1;
static int hf_clnp_segment = -1;
static int hf_clnp_segment_overlap = -1;
@ -185,6 +193,7 @@ static GHashTable *clnp_reassembled_table = NULL;
static guint tp_nsap_selector = NSEL_TP;
static gboolean always_decode_transport = FALSE;
static gboolean clnp_reassemble = TRUE;
gboolean clnp_decode_atn_options = FALSE;
/* function definitions */
@ -250,7 +259,7 @@ dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/* fixed part decoding */
cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
opt_len = cnf_hdr_len;
if (tree) {
ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA);
clnp_tree = proto_item_add_subtree(ti, ett_clnp);
@ -342,7 +351,7 @@ dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
cnf_cksum);
break;
}
opt_len -= 9; /* Fixed part of Hesder */
opt_len -= 9; /* Fixed part of Header */
} /* tree */
/* address part */
@ -354,6 +363,10 @@ dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
src_len = tvb_get_guint8(tvb, offset + dst_len + 1);
src_addr = tvb_get_ptr(tvb, offset + dst_len + 2, src_len);
/* store src & dst address parts for ATN extended checksum calculation in ositp.c */
clnp_pt_len = dst_len + src_len + 2;
tvb_memcpy(tvb, &clnp_pt_buffer, offset, sizeof(clnp_pt_buffer));
if (tree) {
proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
dst_len);
@ -595,7 +608,13 @@ proto_register_clnp(void)
{ &hf_clnp_src,
{ "SA", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_clnp_segment_overlap,
{ &hf_clnp_atntt,
{ "ATN traffic type", "clnp.atn.tt", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_clnp_atnsc,
{ "ATN security classification", "clnp.atn.sc", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_clnp_segment_overlap,
{ "Segment overlap", "clnp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"Segment overlaps with other segments", HFILL }},
@ -665,6 +684,14 @@ proto_register_clnp(void)
"Reassemble segmented CLNP datagrams",
"Whether segmented CLNP datagrams should be reassembled",
&clnp_reassemble);
prefs_register_bool_preference(clnp_module, "decode_atn_options",
"Decode ATN security label",
"Whether ATN security label should be decoded",
&clnp_decode_atn_options);
/* init src & dst address parts for ATN extended checksum calculation in ositp.c */
memset(clnp_pt_buffer, 0, sizeof(clnp_pt_buffer));
clnp_pt_len = 0;
}
void

View File

@ -41,6 +41,46 @@
#include "packet-esis.h"
#include "packet-osi-options.h"
/* ATN traffic types (ICAO doc 9705 Edition3 SV5 5.6.2.2.6.7.3) */
#define ATN_TT_ATSC_NO_PREFERENCE 0x01
#define ATN_TT_ATSC_CLASS_A 0x10
#define ATN_TT_ATSC_CLASS_B 0x11
#define ATN_TT_ATSC_CLASS_C 0x12
#define ATN_TT_ATSC_CLASS_D 0x13
#define ATN_TT_ATSC_CLASS_E 0x14
#define ATN_TT_ATSC_CLASS_F 0x15
#define ATN_TT_ATSC_CLASS_G 0x16
#define ATN_TT_ATSC_CLASS_H 0x17
#define ATN_TT_AOC_NO_PREFERENCE 0x21
#define ATN_TT_AOC_G 0x22
#define ATN_TT_AOC_V 0x23
#define ATN_TT_AOC_S 0x24
#define ATN_TT_AOC_H 0x25
#define ATN_TT_AOC_M 0x26
#define ATN_TT_AOC_G_V 0x27
#define ATN_TT_AOC_G_V_S 0x28
#define ATN_TT_AOC_G_V_H_S 0x29
#define ATN_TT_ADM_NO_PREFERENCE 0x30
#define ATN_TT_SYS_MGMT_NO_PREFERENCE 0x50
/* ATN security classification (ICAO doc 9705 Edition3 SV5 5.6.2.2.6.8.3) */
#define ATN_SC_UNCLASSIFIED 0x01
#define ATN_SC_RESTRICTED 0x02
#define ATN_SC_CONFIDENTIAL 0x03
#define ATN_SC_SECRET 0x04
#define ATN_SC_TOP_SECRET 0x05
/* ATN security label records */
#define OSI_OPT_SECURITY_ATN_SR 0xc0
#define OSI_OPT_SECURITY_ATN_TT 0x0f
#define OSI_OPT_SECURITY_ATN_SC 0x03
#define OSI_OPT_SECURITY_ATN_SR_LEN 6
#define OSI_OPT_SECURITY_ATN_TT_LEN 1
#define OSI_OPT_SECURITY_ATN_SC_LEN 1
#define OSI_OPT_SECURITY_ATN_SI_MAX_LEN 8
#define OSI_OPT_SECURITY 0xc5
#define OSI_OPT_QOS_MAINTANANCE 0xc3
#define OSI_OPT_PRIORITY 0xcd
@ -85,13 +125,56 @@
#define OSI_OPT_RFD_MASK 0xf0
#define OSI_OPT_RFD_SUB_MASK 0x0f
extern gboolean clnp_decode_atn_options; /* as defined in packet-clnp.c */
extern int hf_clnp_atntt; /* as defined in packet-clnp.c */
extern int hf_clnp_atnsc; /* as defined in packet-clnp.c */
static gint ott_osi_options = -1;
static gint ott_osi_qos = -1;
static gint ott_osi_route = -1;
static gint ott_osi_redirect = -1;
static const guchar atn_security_registration_val[] = { 0x06, 0x04, 0x2b, 0x1b, 0x00, 0x00 }; /* =iso(1).org(3).ICAO(27).ATN(0).TrafficType(0)*/
static const value_string osi_opt_sec_atn_sr_vals[] = {
{ OSI_OPT_SECURITY_ATN_SR, "ATN Security Label"},
{ 0, NULL} };
static const value_string osi_opt_sec_atn_si_vals[] = {
{ OSI_OPT_SECURITY_ATN_TT, "Traffic Type and Routing"},
{ OSI_OPT_SECURITY_ATN_SC, "Security classification"},
{ 0, NULL} };
static const value_string osi_opt_sec_atn_tt_vals[] = {
{ ATN_TT_ATSC_NO_PREFERENCE, "ATSC No preference"},
{ ATN_TT_ATSC_CLASS_A, "ATSC Class A"},
{ ATN_TT_ATSC_CLASS_B, "ATSC Class B"},
{ ATN_TT_ATSC_CLASS_C, "ATSC Class C"},
{ ATN_TT_ATSC_CLASS_D, "ATSC Class D"},
{ ATN_TT_ATSC_CLASS_E, "ATSC Class E"},
{ ATN_TT_ATSC_CLASS_F, "ATSC Class F"},
{ ATN_TT_ATSC_CLASS_G, "ATSC Class G"},
{ ATN_TT_ATSC_CLASS_H, "ATSC Class H"},
{ ATN_TT_AOC_NO_PREFERENCE, "AOC No preference"},
{ ATN_TT_AOC_G, "AOC Gatelink only"},
{ ATN_TT_AOC_V, "AOC VHF only"},
{ ATN_TT_AOC_S, "AOC Satellite only"},
{ ATN_TT_AOC_H, "AOC HF only"},
{ ATN_TT_AOC_M, "AOC Mode S only"},
{ ATN_TT_AOC_G_V, "AOC Gatelink first, then VHF"},
{ ATN_TT_AOC_G_V_S, "AOC Gatelink first, then VHF, then Satellite"},
{ ATN_TT_AOC_G_V_H_S, "AOC Gatelink first, then VHF, then HF, then Satellite"},
{ ATN_TT_ADM_NO_PREFERENCE, "ATN Administrative No preference"},
{ ATN_TT_SYS_MGMT_NO_PREFERENCE,"ATN Systems Management No preference"},
{ 0, NULL} };
static const value_string osi_opt_sec_atn_sc_vals[] = {
{ ATN_SC_UNCLASSIFIED, "unclassified"},
{ ATN_SC_RESTRICTED, "restricted"},
{ ATN_SC_CONFIDENTIAL, "confidential"},
{ ATN_SC_SECRET, "secret"},
{ ATN_SC_TOP_SECRET, "top secret"},
{ 0, NULL} };
static const value_string osi_opt_sec_vals[] = {
{ OSI_OPT_SEC_RESERVED, "Reserved"},
@ -337,6 +420,108 @@ dissect_option_rfd( const guchar error, const guchar field, int offset,
}
}
/* dissect ATN security label used for policy based interdomain routing.*/
/* For details see ICAO doc 9705 Edition 3 SV5 5.6.2.2.2.2 */
static void
dissect_option_atn_security_label(
const guchar sub_type,
guchar length,
tvbuff_t *tvb,
guint offset,
proto_tree *tree ) {
proto_item *ti;
proto_tree *atn_sl_tree = NULL;
guchar len = 0;
guint8 tag_name = 0;
guint security_info_end = 0;
/* check for ATN security label */
if( OSI_OPT_SECURITY_ATN_SR != sub_type ){
return; } /* FALLTHROUGH */
/* check Security Registration Length */
len = tvb_get_guint8(tvb, ++offset);
if( OSI_OPT_SECURITY_ATN_SR_LEN != len ){
return; } /* FALLTHROUGH */
/* check Security Registration ID */
if (tvb_memeql(tvb, ++offset , atn_security_registration_val, OSI_OPT_SECURITY_ATN_SR_LEN )){
return; } /* FALLTHROUGH */
ti = proto_tree_add_text( tree, tvb, offset, length,
"%s",
val_to_str( sub_type, osi_opt_sec_atn_sr_vals, "Unknown (0x%x)"));
atn_sl_tree = proto_item_add_subtree( ti, ott_osi_qos );
offset+=OSI_OPT_SECURITY_ATN_SR_LEN ;
/* Security Information length */
len = tvb_get_guint8(tvb, offset);
if(OSI_OPT_SECURITY_ATN_SI_MAX_LEN < len){
/* FALLTHROUGH */
return;}
offset++;
security_info_end = offset + len;
while( offset < security_info_end ){
/* check tag name length*/
len = tvb_get_guint8(tvb, offset ); /* check tag name length*/
if( len != 1 ){
return; } /* FALLTHROUGH */
offset++;
tag_name = tvb_get_guint8(tvb, offset);
offset++;
switch(tag_name){
case OSI_OPT_SECURITY_ATN_TT:
/* check tag set length*/
len = tvb_get_guint8(tvb, offset);
if( len != OSI_OPT_SECURITY_ATN_TT_LEN ){
return; } /* FALLTHROUGH */
offset ++;
proto_tree_add_uint_format(atn_sl_tree, hf_clnp_atntt, tvb, offset, 1,
tvb_get_guint8(tvb, offset ),
"%s: %s",
val_to_str( OSI_OPT_SECURITY_ATN_TT, osi_opt_sec_atn_si_vals, "Unknown (0x%x)"),
val_to_str( tvb_get_guint8(tvb, offset ), osi_opt_sec_atn_tt_vals, "Unknown (0x%x)") );
offset += len ;
break;
case OSI_OPT_SECURITY_ATN_SC:
/* check tag set length*/
len = tvb_get_guint8(tvb, offset );
if( len != OSI_OPT_SECURITY_ATN_SC_LEN ){
/* FALLTHROUGH */
return;
}
offset ++;
proto_tree_add_uint_format(atn_sl_tree, hf_clnp_atnsc, tvb, offset, 1,
tvb_get_guint8(tvb, offset ),
"%s: %s",
val_to_str( OSI_OPT_SECURITY_ATN_SC, osi_opt_sec_atn_si_vals, "Unknown (0x%x)"),
val_to_str( tvb_get_guint8(tvb, offset ), osi_opt_sec_atn_sc_vals, "Unknown (0x%x)") );
offset += len ;
break;
default:
/* FALLTHROUGH */
return;
}
}
}
/* ############################## Dissection Functions ###################### */
/*
@ -391,10 +576,16 @@ dissect_osi_options( guchar opt_len, tvbuff_t *tvb,
break;
case OSI_OPT_SECURITY:
octet = tvb_get_guint8(tvb, offset);
proto_tree_add_text( osi_option_tree, tvb, offset, parm_len,
if ( clnp_decode_atn_options ){
dissect_option_atn_security_label(octet,parm_len,tvb, offset, osi_option_tree );
}else {
proto_tree_add_text( osi_option_tree, tvb, offset, parm_len,
"Security type: %s",
val_to_str( octet&OSI_OPT_SEC_MASK,
osi_opt_sec_vals, "Unknown (0x%x)") );
osi_opt_sec_vals, "Unknown (0x%x)") );
}
break;
case OSI_OPT_PRIORITY:
octet = tvb_get_guint8(tvb, offset);

View File

@ -194,6 +194,155 @@ check_and_get_checksum( tvbuff_t *tvb, int offset, guint len, guint checksum, in
return( CKSUM_OK );
}
/* 4 octet ATN extended checksum: ICAO doc 9705 Ed3 Volume V section 5.5.4.6.4 */
/* It is calculated over TP4 userdata (all checksums set to zero ) and a pseudo tailer */
/* of length SRC-NSAP, SRC-NSAP, length DST-NSAP, DST-NSAP and ATN extended checksum. */
/* In case of a CR TPDU, the value of the ISO 8073 16-bit fletcher checksum parameter shall */
/* be set to zero. */
gboolean check_atn_ec_32(
tvbuff_t *tvb, guint tdpu_len,
guint offset_ec_32_val, /* offset ATN extended checksum value, calculated at last as part of pseudo trailer */
guint offset_iso8073_val, /* offset ISO 8073 fletcher checksum, CR only*/
guint clnp_pt_len, /* length of NSAP part of pseudo trailer */
guint8 * clnp_pt_buffer){ /* NSAP part of pseudo trailer */
guint i = 0;
guint32 c0 = 0;
guint32 c1 = 0;
guint32 c2 = 0;
guint32 c3 = 0;
guint32 sum = 0;
/* sum accross complete TDPU */
for ( i =0; i< tdpu_len; i++){
c0 += tvb_get_guint8(tvb, i) ;
if( ( i >= offset_ec_32_val ) && /* ignore 32 bit ATN extended checksum value */
( i < ( offset_ec_32_val + 4 ) ) ){
c0 -= tvb_get_guint8(tvb, i); }
if( ( offset_iso8073_val ) && /* ignore 16 bit ISO 8073 checksum, if present*/
( i >= offset_iso8073_val ) &&
( i < ( offset_iso8073_val + 2 ) ) ){
c0 -= tvb_get_guint8(tvb, i); }
if ( c0 >= 0x000000FF )
c0 -= 0x00000FF;
c1 += c0;
if ( c1 >= 0x000000FF )
c1 -= 0x000000FF;
c2 += c1;
if ( c2 >= 0x000000FF )
c2 -= 0x000000FF;
c3 += c2;
if ( c3 >= 0x000000FF )
c3 -= 0x000000FF;
}
/* add NSAP part of pseudo trailer */
for ( i =0; i< clnp_pt_len; i++){
c0 += clnp_pt_buffer[i];
if ( c0 >= 0x000000FF )
c0 -= 0x000000FF;
c1 += c0;
if ( c1 >= 0x000000FF )
c1 -= 0x000000FF;
c2 += c1;
if ( c2 >= 0x000000FF )
c2 -= 0x000000FF;
c3 += c2;
if ( c3 >= 0x000000FF )
c3 -= 0x000000FF;
}
/* add with extended checksum as last part of the pseudo trailer */
for ( i = offset_ec_32_val; i< (offset_ec_32_val+4); i++){
c0 += tvb_get_guint8(tvb, i) ;
if ( c0 >= 0x000000FF )
c0 -= 0x00000FF;
c1 += c0;
if ( c1 >= 0x000000FF )
c1 -= 0x000000FF;
c2 += c1;
if ( c2 >= 0x000000FF )
c2 -= 0x000000FF;
c3 += c2;
if ( c3 >= 0x000000FF )
c3 -= 0x000000FF;
}
sum = (c3 << 24) + (c2 << 16 ) + (c1 << 8) + c0 ;
if(!sum)
return TRUE;
else
return FALSE;
}
/* 2 octet ATN extended checksum: ICAO doc 9705 Ed3 Volume V section 5.5.4.6.4 */
/* It is calculated over TP4 userdata (all checksums set to zero ) and a pseudo tailer */
/* of length SRC-NSAP, SRC-NSAP, length DST-NSAP, DST-NSAP and ATN extended checksum. */
/* In case of a CR TPDU, the value of the ISO 8073 16-bit fletcher checksum parameter shall */
/* be set to zero. */
/* this routine is currently *untested* because of the unavailability of samples.*/
gboolean check_atn_ec_16(
tvbuff_t *tvb,
guint tdpu_len,
guint offset_ec_16_val, /* offset ATN extended checksum value, calculated at last as part of pseudo trailer */
guint offset_iso8073_val, /* offset ISO 8073 fletcher checksum, CR only*/
guint clnp_pt_len, /* length of NSAP part of pseudo trailer */
guint8 * clnp_pt_buffer ){ /* NSAP part of pseudo trailer */
guint i = 0;
guint16 c0 = 0;
guint16 c1 = 0;
guint16 sum = 0;
/* sum accross complete TDPU */
for ( i =0; i< tdpu_len; i++){
c0 += tvb_get_guint8(tvb, i);
if( (i >= offset_ec_16_val) && /* ignore 16 bit extended checksum */
(i < (offset_ec_16_val + 2) ) ) {
c0 -= tvb_get_guint8(tvb, i) ; }
if( (i >= offset_iso8073_val) && /* ignore 16 bit ISO 8073 checksum, if present*/
(i < (offset_iso8073_val + 2) ) ) {
c0 -= tvb_get_guint8(tvb, i) ; }
if ( c0 >= 0x00FF )
c0 -= 0x00FF;
c1 += c0;
if ( c1 >= 0x00FF )
c1 -= 0x00FF;
}
/* sum with NSAP part of the pseudo trailer */
for ( i =0; i< clnp_pt_len; i++){
c0 += clnp_pt_buffer[i] ;
c1 += c0;
}
/* add extended checksum as last part of the pseudo trailer */
for ( i = offset_ec_16_val; i< (offset_ec_16_val+2); i++){
c0 += tvb_get_guint8(tvb, i) ;
if ( c0 >= 0x00FF )
c0 -= 0x00FF;
c1 += c0;
if ( c1 >= 0x00FF )
c1 -= 0x00FF;
}
sum = (c1 << 8) + c0 ;
if(!sum)
return TRUE;
else
return FALSE;
}
/* main entry point */
@ -350,5 +499,6 @@ proto_register_osi(void)
"Whether segmented TPKT datagrams should be reassembled",
&tpkt_desegment);
}

View File

@ -87,5 +87,7 @@ typedef enum {
extern cksum_status_t calc_checksum(tvbuff_t *, int, guint, guint);
extern cksum_status_t check_and_get_checksum( tvbuff_t *, int, guint, guint, int, guint16*);
extern gboolean check_atn_ec_32(tvbuff_t *tvb, guint tdpu_len, guint offset_ec_32_val, guint offset_iso8073_val, guint clnp_pt_len, guint8 * clnp_pt_buffer);
extern gboolean check_atn_ec_16( tvbuff_t *tvb, guint tdpu_len, guint offset_ec_16_val, guint offset_iso8073_val, guint clnp_pt_len, guint8 * clnp_pt_buffer );
#endif /* _PACKET_OSI_H */

View File

@ -198,6 +198,18 @@ static const value_string class_option_vals[] = {
number of octets? */
#define is_LI_NORMAL_AK(p) ( ( p & 0x01 ) == 0 )
/* modified TPDU length indicators due to ATN extended checksum */
#define LI_ATN_NORMAL_DT_WITH_CHECKSUM 10 /* ATN 4 octet extended checksum adds 2 octets */
#define LI_ATN_EXTENDED_DT_WITH_CHECKSUM 13 /* ATN 4 octet extended checksum adds 2 octets */
#define LI_ATN_NORMAL_EA_WITH_CHECKSUM 10 /* ATN 4 octet extended checksum adds 2 octets */
#define LI_ATN_EXTENDED_EA_WITH_CHECKSUM 13 /* ATN 4 octet extended checksum adds 2 octets */
#define LI_ATN_NORMAL_RJ 6 /* ATN 4 octet extended checksum adds 2 octets */
#define LI_ATN_EXTENDED_RJ 11 /* ATN 4 octet extended checksum adds 2 octets */
#define LI_ATN_MAX_DC 11 /* ATN 4 octet extended checksum adds 2 octets */
#define LI_ATN_MAX_AK 30 /* ATN 4 octet extended checksum adds 2 octets */
#define LI_ATN_MAX_EA 13 /* ATN 4 octet extended checksum adds 2 octets */
#define LI_ATN_MAX_ER 10 /* ATN 4 octet extended checksum adds 2 octets */
/* variant part */
#define VP_ACK_TIME 0x85
@ -219,7 +231,23 @@ static const value_string class_option_vals[] = {
#define VP_PREF_MAX_TPDU_SIZE 0xF0
#define VP_INACTIVITY_TIMER 0xF2
/* ATN */
/* Parameter codes with bits 7 and 8 are explicitly not */
/* assigned by ISO/IEC 8073, nor is their use precluded. */
/* Parameter codes for ATN defined in ICAO doc 9507 Ed3 SV 5 section 5.5.2.4.3.1 */
#define VP_ATN_EC_32 0x08 /* 4 octet ATN Extended Transport Checksum parameter */
#define VP_ATN_EC_16 0x09 /* 2 octet ATN Extended Transport Checksum parameter */
/* ATN end */
/* pseudo-trailer for ATN extended checksums on TP4 layer*/
/* the checksum is calculated from the TPDU as well als */
/* dst NSAP length, dst NSAP, src NSAP length and src NSAP as encoded in CLNP PDU*/
extern guint clnp_pt_len; /* length of dst-len + dst-nsap + src-len + src-nsap */
extern guint8 clnp_pt_buffer[42]; /* buffer containing CLNP pseudoheader */
static const value_string tp_vpart_type_vals[] = {
{ VP_ATN_EC_16, "ATN extended checksum - 16 bit" },
{ VP_ATN_EC_32, "ATN extended checksum - 32 bit" },
{ VP_ACK_TIME, "ack time" },
{ VP_RES_ERROR, "res error" },
{ VP_PRIORITY, "priority" },
@ -237,9 +265,16 @@ static const value_string tp_vpart_type_vals[] = {
{ VP_OPT_SEL, "options" },
{ VP_PROTO_CLASS, "proto class" },
{ VP_PREF_MAX_TPDU_SIZE, "preferred max TPDU size" },
{ VP_INACTIVITY_TIMER, "inactivity timer" },
{ 0, NULL }
};
static const value_string tp_vpart_checksum_vals[] = {
{ FALSE, "incorrect" },
{ TRUE, "correct" }
};
static int hf_cotp_vp_src_tsap = -1;
static int hf_cotp_vp_dst_tsap = -1;
static int hf_cotp_vp_src_tsap_bytes = -1;
@ -272,6 +307,8 @@ static gboolean cotp_last_fragment = FALSE;
/* options */
static gboolean cotp_reassemble = TRUE;
static gint32 tsap_display = TSAP_DISPLAY_AUTO;
static gboolean cotp_decode_atn = TRUE;
const enum_val_t tsap_display_options[] = {
{"auto", "As strings if printable", TSAP_DISPLAY_AUTO},
@ -285,6 +322,7 @@ const enum_val_t tsap_display_options[] = {
#define MAX_TSAP_LEN 32
static void cotp_frame_end(void)
{
if (!cotp_last_fragment) {
@ -352,9 +390,18 @@ static gboolean ositp_decode_var_part(tvbuff_t *tvb, int offset,
guint8 c1;
guint16 s, s1,s2,s3,s4;
guint32 t1, t2, t3, t4;
guint32 offset_iso8073_checksum = 0;
gint32 i = 0;
guint16 tdpu_length = 0;
guint8 tmp_code = 0;
guint tmp_len = 0;
guint checksum_ok = 0;
guint32 pref_max_tpdu_size;
proto_item *hidden_item;
/* TDPU length needed for ATN checksum calculations */
tdpu_length = offset + vp_length + tvb_length_remaining(tvb, offset + vp_length);
while (vp_length != 0) {
code = tvb_get_guint8(tvb, offset);
proto_tree_add_text(tree, tvb, offset, 1,
@ -373,6 +420,58 @@ static gboolean ositp_decode_var_part(tvbuff_t *tvb, int offset,
vp_length -= 1;
switch (code) {
case VP_ATN_EC_16 : /* ATN */
if (cotp_decode_atn) {
/* if an alternate OSI checksum is present in the currently unprocessed VP section to the checksum algorithm has to know */
/* this may be the case for backward compatible CR TDPU */
if(!offset_iso8073_checksum){
/* search following parameters in VP part for ISO checksum */
for( i = ( offset + length ); i < vp_length; ){
tmp_code = tvb_get_guint8(tvb, i++);
tmp_len = tvb_get_guint8(tvb, i++);
if (tmp_code == VP_CHECKSUM ){
offset_iso8073_checksum = i; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
break;
}
i += tmp_len; }
}
checksum_ok = check_atn_ec_16(tvb, tdpu_length, offset, offset_iso8073_checksum, clnp_pt_len, (guint8 *) &clnp_pt_buffer);
proto_tree_add_text(tree, tvb, offset, length,
"ATN extended checksum : 0x%04x (%s)",
tvb_get_ntohs(tvb, offset),
val_to_str(checksum_ok, tp_vpart_checksum_vals, "?"));
}else {
proto_tree_add_text(tree, tvb, offset, length,"Parameter value: <not shown>");
}
offset += length;
vp_length -= length;
break;
case VP_ATN_EC_32 : /* ATN */
if (cotp_decode_atn) {
/* if an alternate OSI checksum is present in the currently unprocessed VP section the checksum algorithm has to know */
/* this may be the case for backward compatible CR TDPU */
if(!offset_iso8073_checksum){
/* search following parameters in VP part for ISO checksum */
for( i = ( offset + length ); i < vp_length; ){
tmp_code = tvb_get_guint8(tvb, i++);
tmp_len = tvb_get_guint8(tvb, i++);
if (tmp_code == VP_CHECKSUM ){
offset_iso8073_checksum = i; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
break;}
i += tmp_len; }
}
checksum_ok = check_atn_ec_32(tvb, tdpu_length, offset, offset_iso8073_checksum, clnp_pt_len, (guint8 *) &clnp_pt_buffer);
proto_tree_add_text(tree, tvb, offset, length,
"ATN extended checksum : 0x%08x (%s)",
tvb_get_ntohl(tvb, offset),
val_to_str(checksum_ok, tp_vpart_checksum_vals, "?"));
}else {
proto_tree_add_text(tree, tvb, offset, length,"Parameter value: <not shown>");
}
offset += length;
vp_length -= length;
break;
case VP_ACK_TIME:
s = tvb_get_ntohs(tvb, offset);
@ -585,8 +684,10 @@ static gboolean ositp_decode_var_part(tvbuff_t *tvb, int offset,
break;
case VP_CHECKSUM:
offset_iso8073_checksum = offset; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
checksum_ok = calc_checksum(tvb, 0, tdpu_length, tvb_get_ntohs(tvb, offset));
proto_tree_add_text(tree, tvb, offset, length,
"Checksum: 0x%04x", tvb_get_ntohs(tvb, offset));
"Checksum: 0x%04x (%s)", tvb_get_ntohs(tvb, offset),val_to_str( (checksum_ok == CKSUM_OK) ? TRUE : FALSE , tp_vpart_checksum_vals, "?"));
offset += length;
vp_length -= length;
break;
@ -697,10 +798,11 @@ static int ositp_decode_DR(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
guint16 dst_ref, src_ref;
guchar reason;
const char *str;
/* ATN TPDU's tend to be larger than normal OSI, so nothing to do with respect to LI checks */
if (li < LI_MIN_DR)
return -1;
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
@ -753,6 +855,11 @@ static int ositp_decode_DR(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
"Cause: %s", str);
}
/* decode VP */
if (tree) {
ositp_decode_var_part(tvb, offset + P_REASON_IN_DR + 1, li - P_REASON_IN_DR , 4, cotp_tree);
}
offset += li + 1;
expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_CHAT,
@ -785,79 +892,185 @@ static int ositp_decode_DT(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
fragment_data *fd_head;
conversation_t *conv;
/* VP_CHECKSUM is the only parameter allowed in the variable part.
(This means we may misdissect this if the packet is bad and
contains other parameters.) */
switch (li) {
/* note: in the ATN the user is up to chose between 3 different checksums: */
/* standard OSI, 2 or 4 octet extended checksum. */
/* The differences for DT are that the TDPU headers may be enlarged by 2 octets */
/* and that checksum related option codes and option lengths are different. */
/* to not mess up the original OSI dissector LI checking was implemented separately. */
if (!cotp_decode_atn) { /* non ATN, plain OSI*/
case LI_NORMAL_DT_WITH_CHECKSUM :
if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
return -1;
/* FALLTHROUGH */
/* VP_CHECKSUM is the only parameter allowed in the variable part.
(This means we may misdissect this if the packet is bad and
contains other parameters.) */
switch (li) {
case LI_NORMAL_DT_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80 )
tpdu_nr = tpdu_nr & 0x7F;
else
fragment = TRUE;
is_extended = FALSE;
is_class_234 = TRUE;
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
break;
case LI_NORMAL_DT_WITH_CHECKSUM :
if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
return -1;
/* FALLTHROUGH */
case LI_EXTENDED_DT_WITH_CHECKSUM :
if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
return -1;
/* FALLTHROUGH */
case LI_NORMAL_DT_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80 )
tpdu_nr = tpdu_nr & 0x7F;
else
fragment = TRUE;
is_extended = FALSE;
is_class_234 = TRUE;
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
break;
case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80000000 )
tpdu_nr = tpdu_nr & 0x7FFFFFFF;
else
fragment = TRUE;
is_extended = TRUE;
is_class_234 = TRUE;
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
break;
case LI_EXTENDED_DT_WITH_CHECKSUM :
if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
return -1;
/* FALLTHROUGH */
case LI_NORMAL_DT_CLASS_01 :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_0_1);
if ( tpdu_nr & 0x80 )
tpdu_nr = tpdu_nr & 0x7F;
else
fragment = TRUE;
is_extended = FALSE;
is_class_234 = FALSE;
prev_dst_ref = p_get_proto_data (pinfo->fd, proto_clnp);
if (!prev_dst_ref) {
/* First COTP in frame - save previous dst_ref as offset */
prev_dst_ref = se_alloc (sizeof (guint32));
*prev_dst_ref = cotp_dst_ref;
p_add_proto_data (pinfo->fd, proto_clnp, prev_dst_ref);
} else if (cotp_frame_reset) {
cotp_dst_ref = *prev_dst_ref;
}
cotp_frame_reset = FALSE;
cotp_last_fragment = fragment;
dst_ref = cotp_dst_ref;
conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
if (conv) {
/* Found a conversation, also use index for the generated dst_ref */
dst_ref += (conv->index << 16);
}
if (!fragment) {
cotp_dst_ref++;
register_frame_end_routine(pinfo, cotp_frame_end);
}
break;
case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80000000 )
tpdu_nr = tpdu_nr & 0x7FFFFFFF;
else
fragment = TRUE;
is_extended = TRUE;
is_class_234 = TRUE;
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
break;
default : /* bad TPDU */
return -1;
}
case LI_NORMAL_DT_CLASS_01 :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_0_1);
if ( tpdu_nr & 0x80 )
tpdu_nr = tpdu_nr & 0x7F;
else
fragment = TRUE;
is_extended = FALSE;
is_class_234 = FALSE;
prev_dst_ref = p_get_proto_data (pinfo->fd, proto_clnp);
if (!prev_dst_ref) {
/* First COTP in frame - save previous dst_ref as offset */
prev_dst_ref = se_alloc (sizeof (guint32));
*prev_dst_ref = cotp_dst_ref;
p_add_proto_data (pinfo->fd, proto_clnp, prev_dst_ref);
} else if (cotp_frame_reset) {
cotp_dst_ref = *prev_dst_ref;
}
cotp_frame_reset = FALSE;
cotp_last_fragment = fragment;
dst_ref = cotp_dst_ref;
conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
if (conv) {
/* Found a conversation, also use index for the generated dst_ref */
dst_ref += (conv->index << 16);
}
if (!fragment) {
cotp_dst_ref++;
register_frame_end_routine(pinfo, cotp_frame_end);
}
break;
default : /* bad TPDU */
return -1;
} /* li */
} else {
/* check ATN class4 TDPU's here */
/* check packet length indicators of DaTa(DT) TDPU */
/* note: use of checksum depends on the selected RER */
/* (high:non-use medium:16-bit OSI/16-bit ext.ATN low:32-bit ext. ATN) */
/* note: sole use of TP4 class in the ATN */
/* note: normal/extended TDPU numbering is negociable */
switch (li) {
case LI_NORMAL_DT_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80 )
tpdu_nr = tpdu_nr & 0x7F;
else
fragment = TRUE;
is_extended = FALSE;
is_class_234 = TRUE;
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
break;
/* normal DT with 2 octets of OSI or of ATN Extended Checksum */
case LI_NORMAL_DT_WITH_CHECKSUM :
if ( tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM &&
tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16 )
return -1; /* FALLTHROUGH */
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80 )
tpdu_nr = tpdu_nr & 0x7F;
else
fragment = TRUE;
is_extended = FALSE;
is_class_234 = TRUE;
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
break;
/* normal DT with ATN Extended Checksum (4 octets)*/
case LI_ATN_NORMAL_DT_WITH_CHECKSUM :
if ( tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32 )
return -1; /* FALLTHROUGH */
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80 )
tpdu_nr = tpdu_nr & 0x7F;
else
fragment = TRUE;
is_extended = FALSE;
is_class_234 = TRUE;
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
break;
case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80000000 )
tpdu_nr = tpdu_nr & 0x7FFFFFFF;
else
fragment = TRUE;
is_extended = TRUE;
is_class_234 = TRUE;
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
break;
/* extended DT with 2 octets of OSI or of ATN Extended Checksum */
case LI_EXTENDED_DT_WITH_CHECKSUM :
if ( tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM &&
tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16 )
return -1; /* FALLTHROUGH */
/* FALLTHROUGH */
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80000000 )
tpdu_nr = tpdu_nr & 0x7FFFFFFF;
else
fragment = TRUE;
is_extended = TRUE;
is_class_234 = TRUE;
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
break;
/* extended DT with 4 octets ATN Extended Checksum */
case LI_ATN_EXTENDED_DT_WITH_CHECKSUM:
if ( tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32 )
return -1; /* FALLTHROUGH */
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80000000 )
tpdu_nr = tpdu_nr & 0x7FFFFFFF;
else
fragment = TRUE;
is_extended = TRUE;
is_class_234 = TRUE;
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
break;
default : /* bad TPDU */
return -1;
} /* li */
} /* cotp_decode_atn */
pinfo->clnp_dstref = dst_ref;
pinfo->fragmented = fragment;
@ -1011,45 +1224,138 @@ static int ositp_decode_ED(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
guint tpdu_nr;
tvbuff_t *next_tvb;
/* ED TPDUs are never fragmented */
/* note: in the ATN the user is up to chose between 3 different checksums: */
/* standard OSI, 2 or 4 octet extended checksum. */
/* The differences for ED (as for DT) are that the TDPU headers may be enlarged by 2 octets */
/* and that checksum related option codes and option lengths are different. */
/* to not mess up the original OSI dissector LI checking was implemented separately. */
/* note: this could not be tested, because no sample was avail for expedited data */
if (!cotp_decode_atn) { /* non ATN, plain OSI*/
/* ED TPDUs are never fragmented */
/* VP_CHECKSUM is the only parameter allowed in the variable part.
(This means we may misdissect this if the packet is bad and
contains other parameters.) */
switch (li) {
/* VP_CHECKSUM is the only parameter allowed in the variable part.
(This means we may misdissect this if the packet is bad and
contains other parameters.) */
switch (li) {
case LI_NORMAL_DT_WITH_CHECKSUM :
if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
return -1;
/* FALLTHROUGH */
case LI_NORMAL_DT_WITH_CHECKSUM :
if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
return -1;
/* FALLTHROUGH */
case LI_NORMAL_DT_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80 )
tpdu_nr = tpdu_nr & 0x7F;
else
return -1;
is_extended = FALSE;
break;
case LI_NORMAL_DT_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80 )
tpdu_nr = tpdu_nr & 0x7F;
else
return -1;
is_extended = FALSE;
break;
case LI_EXTENDED_DT_WITH_CHECKSUM :
if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
return -1;
/* FALLTHROUGH */
case LI_EXTENDED_DT_WITH_CHECKSUM :
if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
return -1;
/* FALLTHROUGH */
case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80000000 )
tpdu_nr = tpdu_nr & 0x7FFFFFFF;
else
return -1;
is_extended = TRUE;
break;
case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80000000 )
tpdu_nr = tpdu_nr & 0x7FFFFFFF;
else
return -1;
is_extended = TRUE;
break;
default : /* bad TPDU */
return -1;
} /* li */
default : /* bad TPDU */
return -1;
} /* li */
}else {
/* check packet length indicators of ATN Expedited Data (ED) TDPU */
/* note: use of checksum depends on the selected RER */
/* (high:non-use medium:16-bit OSI/16-bit ext.ATN low:32-bit ext. ATN) */
/* note: sole use of TP4 class in the ATN */
/* note: normal/extended TDPU numbering is negociable */
switch (li) {
case LI_NORMAL_DT_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80 )
tpdu_nr = tpdu_nr & 0x7F;
else
return -1;
is_extended = FALSE;
break;
case LI_NORMAL_DT_WITH_CHECKSUM :
if ((tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM) &&
(tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16))
return -1;
/* FALLTHROUGH */
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80 )
tpdu_nr = tpdu_nr & 0x7F;
else
return -1;
is_extended = FALSE;
break;
case LI_ATN_NORMAL_DT_WITH_CHECKSUM :
if ( tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32 )
return -1;
/* FALLTHROUGH */
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80 )
tpdu_nr = tpdu_nr & 0x7F;
else
return -1;
is_extended = FALSE;
break;
case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80000000 )
tpdu_nr = tpdu_nr & 0x7FFFFFFF;
else
return -1;
is_extended = TRUE;
break;
case LI_EXTENDED_DT_WITH_CHECKSUM :
if ( ( tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ) &&
( tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16) )
return -1;
/* FALLTHROUGH */
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80000000 )
tpdu_nr = tpdu_nr & 0x7FFFFFFF;
else
return -1;
is_extended = TRUE;
break;
case LI_ATN_EXTENDED_DT_WITH_CHECKSUM :
if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32)
return -1;
/* FALLTHROUGH */
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
if ( tpdu_nr & 0x80000000 )
tpdu_nr = tpdu_nr & 0x7FFFFFFF;
else
return -1;
is_extended = TRUE;
break;
default : /* bad TPDU */
return -1;
} /* li */
} /* cotp_decode_atn */
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
pinfo->clnp_dstref = dst_ref;
@ -1115,18 +1421,43 @@ static int ositp_decode_RJ(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
guint tpdu_nr;
gushort credit = 0;
switch(li) {
case LI_NORMAL_RJ :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
break;
case LI_EXTENDED_RJ :
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
break;
default :
return -1;
}
/* note: in the ATN the user is up to chose between 3 different checksums: */
/* standard OSI, 2 or 4 octet extended checksum. */
/* The difference for RJ is that the TDPU header may be enlarged by 2 octets */
/* for checksum parameters are not going to be checked here */
if (!cotp_decode_atn) { /* non ATN, plain OSI*/
switch(li) {
case LI_NORMAL_RJ :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
break;
case LI_EXTENDED_RJ :
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
break;
default :
return -1;
}
} else {
switch(li) {
/* normal with 2 octets of OSI or ATN checksum */
case LI_NORMAL_RJ :
/* with 4 octets of ATN checksum */
case LI_ATN_NORMAL_RJ :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
break;
/* extended with 2 octets of OSI or ATN checksum */
case LI_EXTENDED_RJ :
/* with 4 octets of ATN checksum */
case LI_ATN_EXTENDED_RJ :
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
break;
default :
return -1;
}
}
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
pinfo->clnp_dstref = dst_ref;
@ -1168,7 +1499,10 @@ static int ositp_decode_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
gboolean uses_inactive_subset,
gboolean *subdissector_found)
{
/* note: in the ATN the user is up to chose between 3 different checksums: */
/* standard OSI, 2 or 4 octet extended checksum. */
/* Nothing has to be done here, for all ATN specifics are handled in VP. */
/* CC & CR decoding in the same function */
proto_tree *cotp_tree = NULL;
@ -1264,9 +1598,15 @@ static int ositp_decode_DC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
proto_item *item = NULL;
guint16 dst_ref, src_ref;
if (li > LI_MAX_DC)
return -1;
/* ATN may use checksums different from OSI */
/* which may result in different TPDU header length. */
if ( !cotp_decode_atn) {
if (li > LI_MAX_DC)
return -1; }
else {
if (li > LI_ATN_MAX_DC)
return -1; }
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
pinfo->clnp_dstref = dst_ref;
@ -1321,9 +1661,15 @@ static int ositp_decode_AK(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
guint tpdu_nr;
gushort cdt_in_ak;
if (li > LI_MAX_AK)
return -1;
if (!cotp_decode_atn ){
if (li > LI_MAX_AK)
return -1;}
else {
if (li > LI_ATN_MAX_AK)
return -1; }
/* is_LI_NORMAL_AK() works for normal ATN AK's, */
/* for the TPDU header size may be enlarged by 2 octets */
if (is_LI_NORMAL_AK(li)) {
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
@ -1426,41 +1772,134 @@ static int ositp_decode_EA(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
gboolean is_extended;
guint16 dst_ref;
guint tpdu_nr;
/* Due to different checksums in the ATN the TDPU header sizes */
/* as well as the checksum parameters may be different than plain OSI EA.*/
/* because these are heavily checked for EA these checks had to be re-implemented. */
/* note: this could not be tested, because no sample was avail for expedited data */
if(!cotp_decode_atn) {
if (li > LI_MAX_EA)
return -1;
if (li > LI_MAX_EA)
return -1;
/* VP_CHECKSUM is the only parameter allowed in the variable part.
/* VP_CHECKSUM is the only parameter allowed in the variable part.
(This means we may misdissect this if the packet is bad and
contains other parameters.) */
switch (li) {
switch (li) {
case LI_NORMAL_EA_WITH_CHECKSUM :
if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM ||
tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
return -1;
/* FALLTHROUGH */
case LI_NORMAL_EA_WITH_CHECKSUM :
if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM ||
tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
return -1;
/* FALLTHROUGH */
case LI_NORMAL_EA_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
is_extended = FALSE;
break;
case LI_NORMAL_EA_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
is_extended = FALSE;
break;
case LI_EXTENDED_EA_WITH_CHECKSUM :
if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ||
tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
return -1;
/* FALLTHROUGH */
case LI_EXTENDED_EA_WITH_CHECKSUM :
if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ||
tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
return -1;
/* FALLTHROUGH */
case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
is_extended = TRUE;
break;
case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
is_extended = TRUE;
break;
default : /* bad TPDU */
return -1;
} /* li */
default : /* bad TPDU */
return -1;
} /* li */
}else { /* cotp_decode_atn */
/* check for ATN length: TDPU may be 2 octets longer due to checksum */
if (li > LI_ATN_MAX_EA)
return -1;
switch (li) {
/* extended TDPU numbering EA with no checksum */
case LI_NORMAL_EA_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
is_extended = FALSE;
break;
/* normal TDPU numbering EA with 2 octets of OSI or ATN extended checksum */
case LI_NORMAL_EA_WITH_CHECKSUM :
/* check checksum parameter (in VP) parameter code octet */
if ((tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM) &&
(tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16 ))
return -1;
/* FALLTHROUGH */
/* check checksum parameter (in VP) length octet */
if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT +1 ) != 2)
return -1;
/* FALLTHROUGH */
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
is_extended = FALSE;
break;
/* normal TDPU numbering EA with 4 octets of ATN extended checksum */
case LI_ATN_NORMAL_EA_WITH_CHECKSUM :
/* check checksum parameter (in VP) parameter code octet */
if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32 )
return -1;
/* FALLTHROUGH */
/* check checksum parameter (in VP) length octet */
if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT +1 ) != 4)
return -1;
/* FALLTHROUGH */
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
is_extended = FALSE;
break;
/* extended TDPU numbering EA with no checksum */
case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
is_extended = TRUE;
break;
/* extended TDPU numbering EA with 2 octets of OSI or ATN extended checksum */
case LI_EXTENDED_EA_WITH_CHECKSUM :
/* check checksum parameter (in VP) parameter code octet */
if ( (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ) &&
(tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16))
return -1;
/* FALLTHROUGH */
/* check checksum parameter (in VP) length octet */
if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT +1 ) != 2 )
return -1;
/* FALLTHROUGH */
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
is_extended = TRUE;
break;
/* extended EA with 4 octets ATN extended checksum */
case LI_ATN_EXTENDED_EA_WITH_CHECKSUM :
/* check checksum parameter (in VP) parameter code octet */
if ( tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32 )
return -1;
/* FALLTHROUGH */
/* check checksum parameter (in VP) length octet */
if ( tvb_get_guint8(tvb, offset + P_VAR_PART_EDT +1 ) != 2 )
return -1;
/* FALLTHROUGH */
tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
is_extended = TRUE;
break;
default : /* bad TPDU */
return -1;
}
}
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
pinfo->clnp_dstref = dst_ref;
@ -1518,8 +1957,14 @@ static int ositp_decode_ER(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
const char *str;
guint16 dst_ref;
if (li > LI_MAX_ER)
return -1;
/* ATN: except for modified LI checking nothing to be done here */
if(!cotp_decode_atn) {
if (li > LI_MAX_ER)
return -1;
}else {
if (li > LI_ATN_MAX_ER)
return -1;
}
switch(tvb_get_guint8(tvb, offset + P_REJECT_ER)) {
case 0 :
@ -1826,7 +2271,7 @@ void proto_register_cotp(void)
{ &hf_cotp_vp_dst_tsap_bytes,
{ "Destination TSAP", "cotp.dst-tsap-bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
"Called TSAP (bytes representation)", HFILL }},
};
static gint *ett[] = {
&ett_cotp,
@ -1854,12 +2299,19 @@ void proto_register_cotp(void)
tsap_display_options,
FALSE);
prefs_register_bool_preference(cotp_module, "decode_atn",
"Decode ATN TPDUs",
"Whether to decode OSI TDPUs with ATN (Aereonautical Telecommunications Network) extensions."
" To use this option, you must also enable \"Always try to decode NSDU as transport PDUs\" in the CLNP protocol settings.",
&cotp_decode_atn);
/* subdissector code in inactive subset */
register_heur_dissector_list("cotp_is", &cotp_is_heur_subdissector_list);
/* other COTP/ISO 8473 subdissectors */
register_heur_dissector_list("cotp", &cotp_heur_subdissector_list);
/* XXX - what about CLTP and proto_cltp? */
new_register_dissector("ositp", dissect_ositp, proto_cotp);
new_register_dissector("ositp_inactive", dissect_ositp_inactive, proto_cotp);