/* ICMP Templates in TTCN-3
 * (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
 * All rights reserved.
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

module ICMP_Templates {

	import from General_Types all;
	import from IP_Types all;
	import from ICMP_Types all;

	/* template for sending an ICMPv4 echo request */
	template (value) PDU_ICMP ts_ICMPv4_ERQ(octetstring data := ''O) := {
		echo := {
			type_field := 8,
			code := 0,
			checksum := '0000'O,
			identifier := '0345'O,
			sequence_number := '0001'O,
			data := data
		}
	}

	/* template for receiving/matching an ICMPv4 echo request */
	template (present) PDU_ICMP tr_ICMPv4_ERQ := {
		echo := {
			type_field := 8,
			code := 0,
			checksum := ?,
			identifier := ?,
			sequence_number := ?,
			data := ?
		}
	}

	/* template for receiving/matching an ICMPv4 echo reply */
	template (present) PDU_ICMP tr_ICMPv4_ERP(template octetstring data := *) := {
		echo_reply := {
			type_field := 0,
			code := 0,
			checksum := ?,
			identifier := ?,
			sequence_number := ?,
			data := data
		}
	}

	/* template for receiving/matching an ICMPv6 Destination Unreachable  */
	template (present) PDU_ICMP tr_ICMPv4_DU := {
		destination_unreachable := {
			type_field := 1,
			code := ?,
			checksum := ?,
			unused := ?,
			original_ip_msg  := ?
		}
	}

	/* template to construct IPv4_packet from input arguments, ready for use in f_IPv4_enc() */
	template (value) IPv4_packet ts_IP4(OCT4 srcaddr, OCT4 dstaddr, LIN1 proto, LIN2_BO_LAST tlen, octetstring payload) := {
		header := {
			ver := 4,
			hlen := 5,
			tos := 0,
			tlen := tlen,
			id := 35902,
			res := '0'B,
			dfrag := '1'B,
			mfrag := '0'B,
			foffset := 0,
			ttl := 64,
			proto := proto,
			cksum := 0,
			srcaddr := srcaddr,
			dstaddr := dstaddr
		},
		ext_headers := omit,
		payload := payload
	}

	/* Send an ICMPv4 echo msg through GTP given pdp ctx, and ip src and dst addr */
	function f_gen_icmpv4_echo(OCT4 saddr, OCT4 daddr, octetstring pl := ''O) return octetstring {
		var octetstring tmp := f_enc_PDU_ICMP(valueof(ts_ICMPv4_ERQ(pl)));
		var IPv4_packet ip4 := valueof(ts_IP4(saddr, daddr, 1, 50, tmp));
		var octetstring data := f_IPv4_enc(ip4);
		var OCT2 cksum := f_IPv4_checksum(data);
		data[10] := cksum[0];
		data[11] := cksum[1];
		return data;
	}
}