238 lines
6.6 KiB
Plaintext
238 lines
6.6 KiB
Plaintext
/* 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);
|
|
}
|
|
|
|
} |