blob: 687aad45f761e631594e35865a8ff952c33cf657 [file] [log] [blame]
Pau Espin Pedrole16e9282024-03-01 14:45:22 +01001/* ICMPv6 Templates in TTCN-3
2 * (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
3 * All rights reserved.
4 *
5 * Released under the terms of GNU General Public License, Version 2 or
6 * (at your option) any later version.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11module ICMPv6_Templates {
12
13 import from General_Types all;
14 import from IP_Types all;
15 import from ICMPv6_Types all;
16
17 /* template to generate a 'Prefix Information' ICMPv6 option */
18 template (value) OptionField ts_ICMP6_OptPrefix(OCT16 prefix, INT1 prefix_len) := {
19 prefixInformation := {
20 typeField := 3,
21 lengthIndicator := 8,
22 prefixLength := prefix_len,
23 reserved1 := '000000'B,
24 a_Bit := '0'B,
25 l_Bit := '0'B,
26 validLifetime := oct2int('FFFFFFFF'O),
27 preferredLifetime := oct2int('FFFFFFFF'O),
28 reserved2 := '00000000'O,
29 prefix := prefix
30 }
31 }
32
33 /* template for sending an ICMPv6 echo request */
34 template (value) PDU_ICMPv6 ts_ICMPv6_ERQ := {
35 echoRequest := {
36 typeField := 128,
37 code := 0,
38 checksum := '0000'O,
39 identifier := 0,
40 sequenceNr := 0,
41 data := ''O
42 }
43 }
44
45 /* template for sending an ICMPv6 router solicitation */
46 template (value) PDU_ICMPv6 ts_ICMPv6_RS := {
47 routerSolicitation := {
48 typeField := 133,
49 code := 0,
50 checksum := '0000'O,
51 reserved := '00000000'O,
52 /* TODO: do we need 'Source link-layer address' ? */
53 options := omit
54 }
55 }
56
57 /* template for sending an ICMPv6 router advertisement */
58 template (value) PDU_ICMPv6 ts_ICMPv6_RA(OCT16 prefix, INT1 prefix_len) := {
59 routerAdvertisement := {
60 typeField := 134,
61 code := 0,
62 checksum := '0000'O,
63 curHopLimit := 0,
64 reserved := '000000'B,
65 o_Bit := '0'B,
66 m_Bit := '0'B,
67 routerLifetime := oct2int('FFFF'O),
68 reachableTime := oct2int('FFFFFFFF'O),
69 retransTimer := oct2int('FFFFFFFF'O),
70 options := {
71 ts_ICMP6_OptPrefix(prefix, prefix_len)
72 }
73 }
74 }
75
76 /* template for sending an ICMPv6 neighbor solicitation */
77 template (value) PDU_ICMPv6 ts_ICMPv6_NS(OCT16 target_addr) := {
78 neighborSolicitation := {
79 typeField := 135,
80 code := 0,
81 checksum := '0000'O,
82 reserved := '00000000'O,
83 targetAddress := target_addr,
84 /* TODO: do we need 'Source link-layer address' ? */
85 options := omit
86 }
87 }
88
89 /* derive ICMPv6 link-local address from lower 64bit of link_id */
90 /* template for receiving/matching an ICMPv6 'Prefix Information' option */
91 template (present) OptionField tr_ICMP6_OptPrefix(template (present) OCT16 prefix, template (present) INT1 prefix_len) := {
92 prefixInformation := {
93 typeField := 3,
94 lengthIndicator := 4,
95 prefixLength := prefix_len,
96 reserved1 := ?,
97 a_Bit := ?,
98 l_Bit := ?,
99 validLifetime := ?,
100 preferredLifetime := ?,
101 reserved2 := ?,
102 prefix := prefix
103 }
104 }
105
106 /* template for receiving/matching an ICMPv6 'MTU' option, rfc4861 4.6.4 */
107 template (present) OptionField tr_ICMP6_OptMTU(template (present) integer mtu := ?) := {
108 mTU := {
109 typeField := 5,
110 lengthIndicator := 1,
111 reserved := ?,
112 mTU_Value := mtu
113 }
114 }
115
116 /* template for receiving/matching an ICMPv6 router advertisement */
117 template (present) PDU_ICMPv6 tr_ICMPv6_RA(template (present) OCT16 prefix, template (present) INT1 prefix_len) := {
118 routerAdvertisement := {
119 typeField := 134,
120 code := 0,
121 checksum := ?,
122 curHopLimit := ?,
123 reserved := ?,
124 o_Bit := '0'B,
125 m_Bit := '0'B,
126 routerLifetime := ?,
127 reachableTime := ?,
128 retransTimer := ?,
129 options := ({ tr_ICMP6_OptPrefix(prefix, prefix_len) },
130 { tr_ICMP6_OptPrefix(prefix, prefix_len), tr_ICMP6_OptMTU }
131 )
132 }
133 }
134
135 /* template for receiving/matching an ICMPv6 Destination Unreachable */
136 template (present) PDU_ICMPv6 tr_ICMPv6_DU := {
137 destinationUnreachable := {
138 typeField := 1,
139 code := ?,
140 checksum := ?,
141 unused := ?,
142 originalIpMsg := ?
143 }
144 }
145
146 /* template for receiving/matching an ICMPv6 echo request */
147 template (present) PDU_ICMPv6 tr_ICMPv6_ERQ := {
148 echoRequest := {
149 typeField := 128,
150 code := 0,
151 checksum := ?,
152 identifier := ?,
153 sequenceNr := ?,
154 data := ?
155 }
156 }
157
158 /* template for receiving/matching an ICMPv6 echo reply */
159 template (present) PDU_ICMPv6 tr_ICMPv6_ERP(template octetstring data := *) := {
160 echoReply := {
161 typeField := 129,
162 code := 0,
163 checksum := ?,
164 identifier := ?,
165 sequenceNr := ?,
166 data := data
167 }
168 }
169
170 /* template to construct IPv6_packet from input arguments, ready for use in f_IPv6_enc() */
171 template (value) IPv6_packet ts_IP6(OCT16 srcaddr, OCT16 dstaddr, LIN1 nexthead, octetstring payload, LIN1 hlim := 255) := {
172 header := {
173 ver := 6,
174 trclass := 0,
175 flabel := 0,
176 plen := 0,
177 nexthead := nexthead,
178 hlim := hlim,
179 srcaddr := srcaddr,
180 dstaddr := dstaddr
181 },
182 ext_headers := omit,
183 payload := payload
184 }
185
186 function f_ipv6_link_local(in OCT16 link_id) return OCT16 {
187 return 'FE80000000000000'O & substr(link_id, 8, 8);
188 }
189
190 function f_ipv6_global(in OCT16 link_id) return OCT16 {
191 return substr(link_id, 0, 8) & '1234123412341234'O;
192 }
193
194 /* Create a new different IPv6 addr from input. Starts mangling at byte prefix. */
195 function f_ipv6_mangle(in OCT16 addr, in integer prefix := 0) return OCT16 {
196 var integer i;
197 var octetstring res := substr(addr, 0, prefix);
198 for (i := prefix; i < lengthof(addr); i := i + 1) {
199 var octetstring a := addr[i] xor4b '11'O;
200 res := res & a;
201 }
202 return res;
203 }
204
205 /* Send an ICMPv6 echo msg through GTP given pdp ctx, and ip src and dst addr */
206 function f_gen_icmpv6_echo(OCT16 saddr, OCT16 daddr) return octetstring {
207 var octetstring tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_ERQ), saddr, daddr);
208 var IPv6_packet ip6 := valueof(ts_IP6(saddr, daddr, 58, tmp));
209 var octetstring data := f_IPv6_enc(ip6);
210 return data;
211 }
212
213 /* Compute solicited-node multicast address as per RFC4291 2.7.1 */
214 function f_ipv6_sol_node_mcast(in OCT16 addr) return OCT16 {
215 return 'FF0200000000000000000001FF'O & substr(addr, 13, 3);
216 }
217
218 /* generate and encode ICMPv6 router solicitation */
219 function f_gen_icmpv6_router_solicitation(in OCT16 link_id) return octetstring {
220 const OCT16 c_ip6_all_router_mcast := 'FF020000000000000000000000000002'O;
221 var OCT16 saddr := f_ipv6_link_local(link_id);
222
223 var octetstring tmp;
224 tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_RS), saddr, c_ip6_all_router_mcast);
225 var IPv6_packet ip6 := valueof(ts_IP6(saddr, c_ip6_all_router_mcast, 58, tmp));
226
227 return f_IPv6_enc(ip6);
228 }
229
230 /* generate and encode ICMPv6 neighbor solicitation */
231 function f_gen_icmpv6_neigh_solicit(in OCT16 saddr, in OCT16 daddr, in OCT16 tgt_addr) return octetstring {
232 var octetstring tmp;
233 tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_NS(tgt_addr)), saddr, daddr);
234 var IPv6_packet ip6 := valueof(ts_IP6(saddr, daddr, 58, tmp));
235 return f_IPv6_enc(ip6);
236 }
237
238}