// SCTP Conformance Test Suite Implementation
// (C) Copyright Fujitsu Ltd. 2008, 2009
//
// This file is part of the SCTP Conformance Test Suite implementation.
//
// The SCTP Conformance Test Suite implementation is free software;
// you can redistribute it and/or modify it under the terms of
// the GNU General Public License version 2 as published by
// the Free Software Foundation.
//
// The SCTP Conformance Test Suite implementation is distributed in the
// hope that it will be useful, but WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GNU CC; see the file COPYING.  If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
//
// Please send any bug reports or fixes you make to the
// email address(es):
//    networktest sctp <networktest-sctp@lists.sourceforge.net>
//
// Or submit a bug report through the following website:
//    http://networktest.sourceforge.net/
//
// Written or modified by:
//    Hiroaki Kago <linuxsctp-kg@ml.css.fujitsu.com>
//    Wei Yongjun <yjwei@cn.fujitsu.com>
//
// Any bugs reported given to us we will try to fix... any fixes shared will
// be incorporated into the next SCTP release.
//

#include "../common/STD_PKT_COMMON.def"

#define PMTU	1280

#if (ENABLE_IPV6 == 0)

FEM_icmp4_destination_unreachable(
	icmp_pkt_too_big,
	_HETHER_tn2nut,
	{
		_SRC(v4(SCTP4_TN_NET0_ADDR));
		_DST(v4(SCTP4_NUT_NET0_ADDR));
	},
	{
		Code = 4;
		Unused = PMTU;
		payload = errdata;
	}
)

Payload errdata {
	data = left(_PACKET_IPV4_NAME(sctp_chunk_data_big), 64);
}

FEM_hdr_ipv4_exth( 
	sctp_chunk_data_frag_1st,
	_HETHER_nut2tn,
        {
		Protocol = 132;
		FragmentOffset = 0;
		DF = 0;
		MF = 1;
		Identifier = any;
		_SRC(v4(SCTP4_NUT_NET0_ADDR));
		_DST(v4(SCTP4_TN_NET0_ADDR));
        },
        {
		header = _HDR_IPV4_NAME(sctp_chunk_data_frag_1st);
		upper = payload_1st;
        }
)

Payload payload_1st {
	data = substr(_PACKET_IPV4_NAME(sctp_chunk_data_big), 20, PMTU - 24);
}

FEM_hdr_ipv4_exth( 
	sctp_chunk_data_frag_2nd,
	_HETHER_nut2tn,
        {
		Protocol = 132;
		FragmentOffset = PMTU / 8 - 3;
		DF = 0;
		MF = 0;
		Identifier = any;
		_SRC(v4(SCTP4_NUT_NET0_ADDR));
		_DST(v4(SCTP4_TN_NET0_ADDR));
        },
        {
		header = _HDR_IPV4_NAME(sctp_chunk_data_frag_2nd);
		upper = payload_2nd;
        }
)

Payload payload_2nd {
	data = right(_PACKET_IPV4_NAME(sctp_chunk_data_big), PMTU - 4);
}

#else 

FEM_icmp6_packet_too_big (
	icmp_pkt_too_big,
	_HETHER_tn2nut,
	{
		_SRC(SCTP6_TN_NET0_ADDR);
		_DST(SCTP6_NUT_NET0_ADDR);
	},
	{
		MTU = PMTU;
		payload = errdata;
	}
)

Payload errdata {
	data = left(_PACKET_IPV6_NAME(sctp_chunk_data_big), 64);
}

FEM_hdr_ipv6_exth(
	sctp_chunk_data_frag_1st,
	_HETHER_nut2tn,
	{
		_SRC(SCTP6_NUT_NET0_ADDR);
		_DST(SCTP6_TN_NET0_ADDR);
	},
	{
		header = _HDR_IPV6_NAME(sctp_chunk_data_frag_1st);
		exthdr = frag_1st;
		upper = payload_1st;
	}
)

Hdr_Fragment frag_1st {
	NextHeader = 132;
	FragmentOffset = 0;
	MFlag = 1;
	Identification = any;
}

Payload payload_1st {
	data = substr(_PACKET_IPV6_NAME(sctp_chunk_data_big), 40, PMTU - 48);
}

FEM_hdr_ipv6_exth(
	sctp_chunk_data_frag_2nd,
	_HETHER_nut2tn,
	{
		_SRC(SCTP6_NUT_NET0_ADDR);
		_DST(SCTP6_TN_NET0_ADDR);
	},
	{
		header = _HDR_IPV6_NAME(sctp_chunk_data_frag_2nd);
		exthdr = frag_2nd;
		upper = payload_2nd;
	}
)

Hdr_Fragment frag_2nd {
	NextHeader = 132;
	FragmentOffset = PMTU / 8 - 6;
	MFlag = 0;
	Identification = any;
}

Payload payload_2nd {
	data = right(_PACKET_IPV6_NAME(sctp_chunk_data_big), PMTU - 8);
}

#endif

//
// SCTP CHUNK_DATA
//
PKG_SCTP_SHORT_RECV(
	sctp_chunk_data_big,
	{
		chunk = chunk_data_big;
	}
)

CHUNK_DATA chunk_data_big {
	UFlag = 0;
#ifdef SACK
	TSN = SACK;
#else
	TSN = any;
#endif
	Identifier = 0;
	SequenceNumber = 0;
#ifdef PROTO
	Protocol = PROTO;
#else
	Protocol = any;
#endif
	payload = data_big;
}

Payload data_big {
#if ENABLE_IPV6
	data = left(data1500, 1432 - 1);
#else
	data = left(data1500, 1452 - 1);
#endif
	data = repeat(0x00, 1);
}

//
// SCTP CHUNK_DATA
//
PKG_SCTP_SHORT_RECV(
	sctp_chunk_data_seg1,
	{
		chunk = chunk_data_seg1;
	}
)

CHUNK_DATA chunk_data_seg1 {
	UFlag = any;
#ifdef SACK
	TSN = SACK;
#else
	TSN = any;
#endif
	BFlag = 1;
	EFlag = 0;
	Identifier = any;
	SequenceNumber = any;
	Protocol = any;
	payload = data_seg1;
}

Payload data_seg1 {
#if ENABLE_IPV6
	data = substr(data_big, 0, PMTU - 68);
#else
	data = substr(data_big, 0, PMTU - 48);
#endif
}

//
// SCTP CHUNK_DATA
//
PKG_SCTP_SHORT_RECV(
	sctp_chunk_data_seg2,
	{
		chunk = chunk_data_seg2;
	}
)

CHUNK_DATA chunk_data_seg2 {
	UFlag = any;
#ifdef SACK
	TSN = SACK;
#else
	TSN = any;
#endif
	BFlag = 0;
	EFlag = 1;
	Identifier = any;
	SequenceNumber = any;
	Protocol = any;
	payload = data_seg2;
}

Payload data_seg2 {
#if ENABLE_IPV6
	data = right(data_big, PMTU - 68);
#else
	data = right(data_big, PMTU - 48);
#endif
}

//
// SCTP CHUNK_SACK
//
PKG_SCTP_SHORT_SEND(
	sctp_chunk_sack_seg,
	{
		chunk = chunk_sack_seg;
	}
)

CHUNK_SACK chunk_sack_seg {
#ifdef SACK
	ACK = SACK;
#endif
	AdvRecvWindow = ARWND;
	NumOfGapAck = 0;
	NumOfDupTSN = 0;
}

