diff options
Diffstat (limited to 'library/ICMPv6_Templates.ttcn')
-rw-r--r-- | library/ICMPv6_Templates.ttcn | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/library/ICMPv6_Templates.ttcn b/library/ICMPv6_Templates.ttcn new file mode 100644 index 00000000..687aad45 --- /dev/null +++ b/library/ICMPv6_Templates.ttcn @@ -0,0 +1,238 @@ +/* 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); + } + +}
\ No newline at end of file |