/* ICMPv6 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 ICMPv6_Templates {

	import from General_Types all;
	import from IP_Types all;
	import from ICMPv6_Types all;

	/* template to generate a 'Prefix Information' ICMPv6 option */
	template (value) OptionField ts_ICMP6_OptPrefix(OCT16 prefix, INT1 prefix_len) := {
		prefixInformation := {
			typeField := 3,
			lengthIndicator := 8,
			prefixLength := prefix_len,
			reserved1 := '000000'B,
			a_Bit := '0'B,
			l_Bit := '0'B,
			validLifetime := oct2int('FFFFFFFF'O),
			preferredLifetime := oct2int('FFFFFFFF'O),
			reserved2 := '00000000'O,
			prefix := prefix
		}
	}

	/* template for sending an ICMPv6 echo request */
	template (value) PDU_ICMPv6 ts_ICMPv6_ERQ := {
		echoRequest := {
			typeField := 128,
			code := 0,
			checksum := '0000'O,
			identifier := 0,
			sequenceNr := 0,
			data := ''O
		}
	}

	/* template for sending an ICMPv6 router solicitation */
	template (value) PDU_ICMPv6 ts_ICMPv6_RS := {
		routerSolicitation := {
			typeField := 133,
			code := 0,
			checksum := '0000'O,
			reserved := '00000000'O,
			/* TODO: do we need 'Source link-layer address' ? */
			options := omit
		}
	}

	/* template for sending an ICMPv6 router advertisement */
	template (value) PDU_ICMPv6 ts_ICMPv6_RA(OCT16 prefix, INT1 prefix_len) := {
		routerAdvertisement := {
			typeField := 134,
			code := 0,
			checksum := '0000'O,
			curHopLimit := 0,
			reserved := '000000'B,
			o_Bit := '0'B,
			m_Bit := '0'B,
			routerLifetime := oct2int('FFFF'O),
			reachableTime := oct2int('FFFFFFFF'O),
			retransTimer := oct2int('FFFFFFFF'O),
			options := {
				ts_ICMP6_OptPrefix(prefix, prefix_len)
			}
		}
	}

	/* template for sending an ICMPv6 neighbor solicitation */
	template (value) PDU_ICMPv6 ts_ICMPv6_NS(OCT16 target_addr) := {
		neighborSolicitation := {
			typeField := 135,
			code := 0,
			checksum := '0000'O,
			reserved := '00000000'O,
			targetAddress := target_addr,
			/* TODO: do we need 'Source link-layer address' ? */
			options := omit
		}
	}

	/* derive ICMPv6 link-local address from lower 64bit of link_id */
	/* template for receiving/matching an ICMPv6 'Prefix Information' option */
	template (present) OptionField tr_ICMP6_OptPrefix(template (present) OCT16 prefix, template (present) INT1 prefix_len) := {
		prefixInformation := {
			typeField := 3,
			lengthIndicator := 4,
			prefixLength := prefix_len,
			reserved1 := ?,
			a_Bit := ?,
			l_Bit := ?,
			validLifetime := ?,
			preferredLifetime := ?,
			reserved2 := ?,
			prefix := prefix
		}
	}

	/* template for receiving/matching an ICMPv6 'MTU' option, rfc4861 4.6.4 */
	template (present) OptionField tr_ICMP6_OptMTU(template (present) integer mtu := ?) := {
		mTU := {
			typeField := 5,
			lengthIndicator := 1,
			reserved := ?,
			mTU_Value := mtu
		}
	}

	/* template for receiving/matching an ICMPv6 router advertisement */
	template (present) PDU_ICMPv6 tr_ICMPv6_RA(template (present) OCT16 prefix, template (present) INT1 prefix_len) := {
		routerAdvertisement := {
			typeField := 134,
			code := 0,
			checksum := ?,
			curHopLimit := ?,
			reserved := ?,
			o_Bit := '0'B,
			m_Bit := '0'B,
			routerLifetime := ?,
			reachableTime := ?,
			retransTimer := ?,
			options := ({ tr_ICMP6_OptPrefix(prefix, prefix_len) },
				    { tr_ICMP6_OptPrefix(prefix, prefix_len), tr_ICMP6_OptMTU }
				   )
		}
	}

	/* template for receiving/matching an ICMPv6 Destination Unreachable  */
	template (present) PDU_ICMPv6 tr_ICMPv6_DU := {
		destinationUnreachable := {
			typeField := 1,
			code := ?,
			checksum := ?,
			unused := ?,
			originalIpMsg  := ?
		}
	}

	/* template for receiving/matching an ICMPv6 echo request */
	template (present) PDU_ICMPv6 tr_ICMPv6_ERQ := {
		echoRequest := {
			typeField := 128,
			code := 0,
			checksum := ?,
			identifier := ?,
			sequenceNr := ?,
			data := ?
		}
	}

	/* template for receiving/matching an ICMPv6 echo reply */
	template (present) PDU_ICMPv6 tr_ICMPv6_ERP(template octetstring data := *) := {
		echoReply := {
			typeField := 129,
			code := 0,
			checksum := ?,
			identifier := ?,
			sequenceNr := ?,
			data := data
		}
	}

	/* template to construct IPv6_packet from input arguments, ready for use in f_IPv6_enc() */
	template (value) IPv6_packet ts_IP6(OCT16 srcaddr, OCT16 dstaddr, LIN1 nexthead, octetstring payload, LIN1 hlim := 255) := {
		header := {
			ver := 6,
			trclass := 0,
			flabel := 0,
			plen := 0,
			nexthead := nexthead,
			hlim := hlim,
			srcaddr := srcaddr,
			dstaddr := dstaddr
		},
		ext_headers := omit,
		payload := payload
	}

	function f_ipv6_link_local(in OCT16 link_id) return OCT16 {
		 return 'FE80000000000000'O & substr(link_id, 8, 8);
	}

	function f_ipv6_global(in OCT16 link_id) return OCT16 {
		 return substr(link_id, 0, 8) & '1234123412341234'O;
	}

	/* Create a new different IPv6 addr from input. Starts mangling at byte prefix. */
	function f_ipv6_mangle(in OCT16 addr, in integer prefix := 0) return OCT16 {
		var integer i;
		var octetstring res := substr(addr, 0, prefix);
		for (i := prefix; i < lengthof(addr); i := i + 1) {
			var octetstring a := addr[i] xor4b '11'O;
			res := res & a;
		}
		return res;
	}

	/* Send an ICMPv6 echo msg through GTP given pdp ctx, and ip src and dst addr */
	function f_gen_icmpv6_echo(OCT16 saddr, OCT16 daddr) return octetstring {
		var octetstring tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_ERQ), saddr, daddr);
		var IPv6_packet ip6 := valueof(ts_IP6(saddr, daddr, 58, tmp));
		var octetstring data := f_IPv6_enc(ip6);
		return data;
	}

	/* Compute solicited-node multicast address as per RFC4291 2.7.1 */
	function f_ipv6_sol_node_mcast(in OCT16 addr) return OCT16 {
		return 'FF0200000000000000000001FF'O & substr(addr, 13, 3);
	}

	/* generate and encode ICMPv6 router solicitation */
	function f_gen_icmpv6_router_solicitation(in OCT16 link_id) return octetstring {
		const OCT16 c_ip6_all_router_mcast := 'FF020000000000000000000000000002'O;
		var OCT16 saddr := f_ipv6_link_local(link_id);

		var octetstring tmp;
		tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_RS), saddr, c_ip6_all_router_mcast);
		var IPv6_packet ip6 := valueof(ts_IP6(saddr, c_ip6_all_router_mcast, 58, tmp));

		return f_IPv6_enc(ip6);
	}

	/* generate and encode ICMPv6 neighbor solicitation */
	function f_gen_icmpv6_neigh_solicit(in OCT16 saddr, in OCT16 daddr, in OCT16 tgt_addr) return octetstring {
		var octetstring tmp;
		tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_NS(tgt_addr)), saddr, daddr);
		var IPv6_packet ip6 := valueof(ts_IP6(saddr, daddr, 58, tmp));
		return f_IPv6_enc(ip6);
	}

}