blob: 97abc4d7ae51c1517e5d8c5d31e24c0a359c3e16 [file] [log] [blame]
Harald Welte379d45a2017-08-03 09:55:15 +02001module GGSN_Tests {
2
Harald Welte94ade362017-08-04 00:36:55 +02003 import from General_Types all;
Harald Welte811651e2017-08-05 15:25:06 +02004 import from Osmocom_Types all;
Harald Welte94ade362017-08-04 00:36:55 +02005 import from IPL4asp_PortType all;
6 import from IPL4asp_Types all;
7 import from GTP_CodecPort all;
8 import from GTP_CodecPort_CtrlFunct all;
Harald Weltec69cf4e2018-02-17 20:57:02 +01009 import from GTP_Templates all;
Harald Welte94ade362017-08-04 00:36:55 +020010 import from GTPC_Types all;
11 import from GTPU_Types all;
Harald Welte71a36022017-12-04 18:55:58 +010012 import from IPCP_Types all;
Harald Welte231b9412017-08-09 17:16:31 +020013 import from IP_Types all;
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +010014 import from ICMP_Types all;
Harald Welte231b9412017-08-09 17:16:31 +020015 import from ICMPv6_Types all;
Harald Welteddeecbb2017-08-18 22:53:30 +020016 import from Native_Functions all;
Stefan Sperlingc479e4f2018-04-03 19:34:16 +020017 import from Osmocom_VTY_Functions all;
18 import from TELNETasp_PortType all;
Harald Welte94ade362017-08-04 00:36:55 +020019
20 const integer GTP0_PORT := 3386;
21 const integer GTP1C_PORT := 2123;
22 const integer GTP1U_PORT := 2152;
Harald Welteddeecbb2017-08-18 22:53:30 +020023
24 modulepar {
Stefan Sperlingcb782b92018-04-03 16:03:15 +020025 /* Default IP addresses. May be overridden by GGSN_Tests configuration files. */
26
27 /* The SGSN simulated by TTCN3 will bind to these addresses for GTP control and GTP user planes. */
Harald Welteddeecbb2017-08-18 22:53:30 +020028 charstring m_bind_ip_gtpc := "127.23.42.1";
29 charstring m_bind_ip_gtpu := "127.23.42.1";
30
Stefan Sperlingcb782b92018-04-03 16:03:15 +020031 /* Addresses the GGSN which is being tested is listening on for SGSN connections. */
Harald Welteddeecbb2017-08-18 22:53:30 +020032 charstring m_ggsn_ip_gtpc := "127.0.0.6";
33 charstring m_ggsn_ip_gtpu := "127.0.0.6";
Pau Espin Pedrolf69a4382018-01-29 13:09:00 +010034
Stefan Sperlingcb782b92018-04-03 16:03:15 +020035 /*
36 * Our tests expect to see these DNS servers in 'Create PDP context responses' sent by the GGSN.
37 * These addresses must therefore match 'ip[v6] dns' options configured in osmo-ggsn.conf.
38 *
39 * These addresses are not expected to serve actual DNS requests. However, tests may expect to be
40 * able to ping these addresses (currently, IPv4 addresses must respond with an ICMP 'echo reply',
41 * and IPv6 addresses may respond with either ICMPv6 'echo reply' or 'destination unreachable').
42 */
Pau Espin Pedrolf69a4382018-01-29 13:09:00 +010043 charstring m_ggsn_ip4_dns1 := "192.168.100.1"
44 charstring m_ggsn_ip4_dns2 := "8.8.8.8"
Pau Espin Pedrol363ba482018-01-29 18:42:00 +010045 charstring m_ggsn_ip6_dns1 := "2001:4860:4860::8888"
46 charstring m_ggsn_ip6_dns2 := "2001:4860:4860::8844"
Stefan Sperlingcb782b92018-04-03 16:03:15 +020047
48 /*
49 * Additional address ranges are defined in osmo-ggsn.conf from which addresses are assigned
50 * to MS "behind" the simulated SGSN. These addresses appear on tun devices used by osmo-ggsn.
51 * The tests expect to be able to send ping packets between any two simulated MS within the same
52 * address range. This requires IP forwarding to be enabled on the corresponding tun interfaces.
53 */
Harald Welteddeecbb2017-08-18 22:53:30 +020054 }
Harald Welte94ade362017-08-04 00:36:55 +020055
Harald Welte811651e2017-08-05 15:25:06 +020056 type set PdpContext {
57 hexstring imsi,
58 octetstring msisdn optional,
59 octetstring apn,
Harald Welteed7a1772017-08-09 20:26:20 +020060 ProtConfigOptions pco_req optional,
61 ProtConfigOptions pco_neg optional,
Harald Welte811651e2017-08-05 15:25:06 +020062 EndUserAddress eua,
Harald Welte231b9412017-08-09 17:16:31 +020063 OCT16 ip6_prefix optional,
Harald Welte811651e2017-08-05 15:25:06 +020064 BIT4 nsapi,
65 /* TEI (Data) local side */
66 OCT4 teid,
67 /* TEI (Control) local side */
68 OCT4 teic,
69 /* TEI (Data) remote side */
70 OCT4 teid_remote,
71 /* TEI (Control) remote side */
Harald Welte5438b9d2017-08-13 13:27:48 +020072 OCT4 teic_remote
Harald Welte811651e2017-08-05 15:25:06 +020073 }
74
Harald Welte94ade362017-08-04 00:36:55 +020075 type component GT_CT {
76 port GTPC_PT GTPC;
77 port GTPU_PT GTPU;
78
Harald Welte0be142b2017-08-13 13:28:10 +020079 var boolean g_initialized := false;
80
Harald Welte94ade362017-08-04 00:36:55 +020081 var OCT1 g_restart_ctr := '01'O;
82 /* FIXME: unify with g_bind_ip + parse from config file */
Harald Welteddeecbb2017-08-18 22:53:30 +020083 var OCT4 g_sgsn_ip_c;
84 var OCT4 g_sgsn_ip_u;
Harald Welte94ade362017-08-04 00:36:55 +020085 /* FIXME: parse remName from config file */
Harald Welteddeecbb2017-08-18 22:53:30 +020086 var GtpPeer g_peer_c := { connId := 0, remName := m_ggsn_ip_gtpc, remPort := GTP1C_PORT };
87 var GtpPeer g_peer_u := { connId := 0, remName := m_ggsn_ip_gtpu, remPort := GTP1U_PORT };
Harald Welte94ade362017-08-04 00:36:55 +020088 timer T_default := 3.0;
Harald Welte5438b9d2017-08-13 13:27:48 +020089
90 /* next to-be-sent GTP-C sequence number */
91 var uint16_t g_c_seq_nr;
92 /* next to-be-sent GTP-U sequence number */
93 var uint16_t g_d_seq_nr;
Stefan Sperlingc479e4f2018-04-03 19:34:16 +020094
95 port TELNETasp_PT GGSNVTY;
Harald Welted2394e92018-04-26 10:21:49 +020096 var boolean use_gtpu_txseq := false;
Stefan Sperlingc479e4f2018-04-03 19:34:16 +020097 }
98
99 private function f_init_vty() runs on GT_CT {
100 map(self:GGSNVTY, system:GGSNVTY);
101 f_vty_set_prompts(GGSNVTY);
102 f_vty_transceive(GGSNVTY, "enable");
103 }
104
105 private function f_vty_set_gpdu_txseq(boolean enable) runs on GT_CT {
106 f_vty_enter_config(GGSNVTY);
107 f_vty_transceive(GGSNVTY, "ggsn ggsn0");
108 f_vty_transceive(GGSNVTY, "apn internet");
109 if (enable) {
110 f_vty_transceive(GGSNVTY, "g-pdu tx-sequence-numbers");
111 } else {
112 f_vty_transceive(GGSNVTY, "no g-pdu tx-sequence-numbers");
113 }
114 f_vty_transceive(GGSNVTY, "end");
115 }
116
117 private function f_verify_gtpu_txseq(in PDU_GTPU gtpu, in boolean expect_gptu_txseq) return boolean {
118 if (expect_gptu_txseq) {
119 if (gtpu.s_bit != '1'B) {
120 log("GTPU sequence number expected but not present")
121 return false;
122 }
123 } else {
124 if (gtpu.s_bit != '0'B) {
125 log("GTPU sequence number not expected but present")
126 return false;
127 }
128 }
129 return true;
Harald Welte94ade362017-08-04 00:36:55 +0200130 }
131
132 function f_init() runs on GT_CT {
Harald Welte0be142b2017-08-13 13:28:10 +0200133 if (g_initialized == true) {
134 return;
135 }
136 g_initialized := true;
137
Harald Welteddeecbb2017-08-18 22:53:30 +0200138 g_sgsn_ip_c := f_inet_addr(m_bind_ip_gtpc);
139 g_sgsn_ip_u := f_inet_addr(m_bind_ip_gtpu);
140
Harald Welte94ade362017-08-04 00:36:55 +0200141 var Result res;
142 map(self:GTPC, system:GTPC);
Harald Welteddeecbb2017-08-18 22:53:30 +0200143 res := GTP_CodecPort_CtrlFunct.f_IPL4_listen(GTPC, m_bind_ip_gtpc, GTP1C_PORT, {udp:={}});
Harald Welte94ade362017-08-04 00:36:55 +0200144 log("GTP1C ConnectionID: ", res.connId);
Harald Welte811651e2017-08-05 15:25:06 +0200145 g_peer_c.connId := res.connId;
Harald Welte94ade362017-08-04 00:36:55 +0200146
147 map(self:GTPU, system:GTPU);
Harald Welteddeecbb2017-08-18 22:53:30 +0200148 res := GTP_CodecPort_CtrlFunct.f_GTPU_listen(GTPU, m_bind_ip_gtpu, GTP1U_PORT, {udp:={}});
Harald Welte811651e2017-08-05 15:25:06 +0200149 g_peer_u.connId:= res.connId;
Harald Welte5438b9d2017-08-13 13:27:48 +0200150
151 g_restart_ctr := f_rnd_octstring(1);
Harald Welte11dbc7b2017-08-13 18:57:56 +0200152 g_c_seq_nr := f_rnd_int(65535);
153 g_d_seq_nr := f_rnd_int(65535);
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200154
155 f_init_vty();
Harald Welte3e0b0392018-04-26 09:46:21 +0200156 f_vty_set_gpdu_txseq(use_gtpu_txseq);
Harald Welte94ade362017-08-04 00:36:55 +0200157 }
158
Harald Welte94ade362017-08-04 00:36:55 +0200159 /* Altstep implementing responses to any incoming echo requests */
160 altstep pingpong() runs on GT_CT {
161 var Gtp1cUnitdata ud;
Harald Welte3af89482017-08-04 16:20:23 +0200162 var Gtp1uUnitdata udu;
Harald Welte94ade362017-08-04 00:36:55 +0200163 [] GTPC.receive(tr_GTPC_PING(?)) -> value ud {
Harald Welte811651e2017-08-05 15:25:06 +0200164 var uint16_t seq := oct2int(ud.gtpc.opt_part.sequenceNumber);
165 GTPC.send(ts_GTPC_PONG(ud.peer, seq, '00'O));
Harald Welte94ade362017-08-04 00:36:55 +0200166 repeat;
167 };
Harald Welte3af89482017-08-04 16:20:23 +0200168 [] GTPU.receive(tr_GTPU_PING(?)) -> value udu {
Harald Welte811651e2017-08-05 15:25:06 +0200169 var uint16_t seq := oct2int(udu.gtpu.opt_part.sequenceNumber);
170 GTPU.send(ts_GTPU_PONG(udu.peer, seq, '00'O));
Harald Welte3af89482017-08-04 16:20:23 +0200171 };
Harald Welte94ade362017-08-04 00:36:55 +0200172 [] T_default.timeout { setverdict(fail); };
173 }
174
Harald Welte811651e2017-08-05 15:25:06 +0200175 /* 'internet' in DNS encoding */
Harald Welteed097432017-08-13 13:28:49 +0200176 const octetstring c_ApnInternet := '08696E7465726E6574'O;
177 const octetstring c_ApnInet6 := '05696E657436'O;
178 const octetstring c_ApnInet46 := '06696E65743436'O;
Harald Welte94ade362017-08-04 00:36:55 +0200179
Harald Welte811651e2017-08-05 15:25:06 +0200180 /* return random NSAPI */
181 function f_rnd_nsapi() return BIT4 {
182 return int2bit(f_rnd_int(16), 4);
183 }
184
185 /* return random TEI[DC] */
186 function f_rnd_tei() return OCT4 {
187 return int2oct(f_rnd_int(4294967296), 4);
188 }
189
190 /* define an (internal) representation of a PDP context */
191 template PdpContext t_DefinePDP(hexstring imsi, octetstring msisdn, octetstring apn,
192 EndUserAddress eua) := {
193 imsi := imsi,
194 msisdn := msisdn,
195 nsapi := f_rnd_nsapi(),
196 apn := apn,
Harald Welteed7a1772017-08-09 20:26:20 +0200197 pco_req := omit,
Harald Welte811651e2017-08-05 15:25:06 +0200198 eua := eua,
199 teid := f_rnd_tei(),
Harald Welte5438b9d2017-08-13 13:27:48 +0200200 teic := f_rnd_tei()
Harald Welte811651e2017-08-05 15:25:06 +0200201 }
202
203 /* send GTP-C for a given context and increment sequence number */
Harald Welte41575e92017-08-13 13:49:57 +0200204 function f_send_gtpc(in template Gtp1cUnitdata data) runs on GT_CT {
Harald Welte811651e2017-08-05 15:25:06 +0200205 GTPC.send(data);
Harald Welte5438b9d2017-08-13 13:27:48 +0200206 g_c_seq_nr := g_c_seq_nr + 1;
Harald Welte811651e2017-08-05 15:25:06 +0200207 }
208
209 /* send GTP-U for a given context and increment sequence number */
Harald Welte231b9412017-08-09 17:16:31 +0200210 function f_send_gtpu(inout PdpContext ctx, in octetstring data) runs on GT_CT {
Harald Welte3e0b0392018-04-26 09:46:21 +0200211 if (use_gtpu_txseq) {
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200212 GTPU.send(ts_GTP1U_GPDU(g_peer_u, g_d_seq_nr, ctx.teid_remote, data));
213 g_d_seq_nr := g_d_seq_nr + 1;
214 } else {
215 GTPU.send(ts_GTP1U_GPDU(g_peer_u, omit, ctx.teid_remote, data));
216 }
Harald Welte811651e2017-08-05 15:25:06 +0200217 }
218
219 /* send a PDP context activation */
220 function f_pdp_ctx_act(inout PdpContext ctx) runs on GT_CT {
Harald Welte94ade362017-08-04 00:36:55 +0200221 var Gtp1cUnitdata ud;
Harald Welte94ade362017-08-04 00:36:55 +0200222 var default d;
223
224 log("sending CreatePDP");
Harald Welte41575e92017-08-13 13:49:57 +0200225 f_send_gtpc(ts_GTPC_CreatePDP(g_peer_c, g_c_seq_nr, ctx.imsi, g_restart_ctr,
Harald Welte811651e2017-08-05 15:25:06 +0200226 ctx.teid, ctx.teic, ctx.nsapi, ctx.eua, ctx.apn,
Harald Welteed7a1772017-08-09 20:26:20 +0200227 g_sgsn_ip_c, g_sgsn_ip_u, ctx.msisdn, ctx.pco_req));
Harald Welte94ade362017-08-04 00:36:55 +0200228 T_default.start;
Harald Welte94ade362017-08-04 00:36:55 +0200229 d := activate(pingpong());
230 alt {
Harald Welte811651e2017-08-05 15:25:06 +0200231 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, createPDPContextResponse, ctx.teic)) -> value ud {
232 var CreatePDPContextResponse cpr := ud.gtpc.gtpc_pdu.createPDPContextResponse;
233 if (cpr.cause.causevalue == '80'O) {
Harald Welte99ef9a42017-08-14 21:42:03 +0200234 /* Check if EUA type corresponds to requested type */
235 if (match(ctx.eua, t_EuaIPv4(?)) and
236 not match(cpr.endUserAddress, tr_EuaIPv4(?))){
237 setverdict(fail);
238 }
239 if (match(ctx.eua, t_EuaIPv6(?)) and
240 not match(cpr.endUserAddress, tr_EuaIPv6(?))) {
241 setverdict(fail);
242 }
243 /* Check if PCO response corresponds to request */
244 if (ispresent(ctx.pco_req)) {
245 if (match(ctx.pco_req, ts_PCO_IPv4_DNS_CONT) and
246 not match(cpr.protConfigOptions, tr_PCO_IPv4_DNS_CONT_resp(?))) {
247 log("IPv4 DNS Container requested, but missing");
248 setverdict(fail);
249 }
250 if (match(ctx.pco_req, ts_PCO_IPv6_DNS) and
251 not match(cpr.protConfigOptions, tr_PCO_IPv6_DNS_resp(?))) {
252 log("IPv6 DNS Container requested, but missing");
253 setverdict(fail);
254 }
255 }
Harald Welte811651e2017-08-05 15:25:06 +0200256 ctx.teid_remote := cpr.teidDataI.teidDataI;
257 ctx.teic_remote := cpr.teidControlPlane.teidControlPlane;
Harald Welte231b9412017-08-09 17:16:31 +0200258 ctx.eua := cpr.endUserAddress;
Harald Welteed7a1772017-08-09 20:26:20 +0200259 ctx.pco_neg := cpr.protConfigOptions;
Harald Welte94ade362017-08-04 00:36:55 +0200260 setverdict(pass);
261 } else {
262 setverdict(fail);
263 }
264 }
265 }
266 deactivate(d);
Harald Welte811651e2017-08-05 15:25:06 +0200267 T_default.stop;
Harald Welte94ade362017-08-04 00:36:55 +0200268 }
269
Harald Welte811651e2017-08-05 15:25:06 +0200270 function f_pdp_ctx_del(PdpContext ctx, template BIT1 teardown_ind) runs on GT_CT {
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200271 var Gtp1cUnitdata ud;
272 var default d;
273
Harald Welte41575e92017-08-13 13:49:57 +0200274 f_send_gtpc(ts_GTPC_DeletePDP(g_peer_c, g_c_seq_nr, ctx.teic_remote, ctx.nsapi, teardown_ind));
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200275 T_default.start;
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200276 d := activate(pingpong());
277 alt {
Harald Welte811651e2017-08-05 15:25:06 +0200278 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, deletePDPContextResponse, ctx.teic)) -> value ud {
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200279 if (ud.gtpc.gtpc_pdu.deletePDPContextResponse.cause.causevalue == '80'O) {
280 setverdict(pass);
281 } else {
282 setverdict(fail);
283 }
284 }
285 }
286 deactivate(d);
Harald Welte811651e2017-08-05 15:25:06 +0200287 T_default.stop;
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200288 }
Harald Welte811651e2017-08-05 15:25:06 +0200289 /* IPv6 router solicitation fe80::2 -> ff02::2 from 02:88:b5:1f:25:59 */
290 const octetstring c_router_solicit := '6000000000103afffe800000000000000000000000000002ff02000000000000000000000000000285009f2b0000000001010288b51f2559'O;
291 /* IPv6 neighbor solicitation fe80::2 -> ff02::1:ff00:2 from 02:88:b5:1f:25:59 */
292 const octetstring c_neigh_solicit:= '6000000000203afffe800000000000000000000000000002ff0200000000000000000001ff00000287009f9600000000fe80000000000000000000000000000201010288b51f2559'O;
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200293
Stefan Sperling6cd217e2018-03-30 15:17:34 +0200294 /* template for sending an ICMPv4 echo request */
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100295 template PDU_ICMP ts_ICMPv4_ERQ := {
296 echo := {
297 type_field := 8,
298 code := 0,
299 checksum := '0000'O,
300 identifier := '0345'O,
301 sequence_number := '0001'O,
302 data := ''O
303 }
304 }
305
Stefan Sperling6cd217e2018-03-30 15:17:34 +0200306 /* template for receiving/matching an ICMPv4 echo request */
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +0100307 template PDU_ICMP tr_ICMPv4_ERQ := {
308 echo := {
309 type_field := 8,
310 code := 0,
311 checksum := ?,
312 identifier := ?,
313 sequence_number := ?,
314 data := ?
315 }
316 }
317
Stefan Sperling6cd217e2018-03-30 15:17:34 +0200318 /* template for receiving/matching an ICMPv4 echo reply */
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100319 template PDU_ICMP tr_ICMPv4_ERP(template octetstring data := *) := {
320 echo_reply := {
321 type_field := 0,
322 code := 0,
323 checksum := ?,
324 identifier := ?,
325 sequence_number := ?,
326 data := data
327 }
328 }
329
330 /* template for receiving/matching an ICMPv6 Destination Unreachable */
331 template PDU_ICMP tr_ICMPv4_DU := {
332 destination_unreachable := {
333 type_field := 1,
334 code := ?,
335 checksum := ?,
336 unused := ?,
337 original_ip_msg := ?
338 }
339 }
340
341 /* template to construct IPv4_packet from input arguments, ready for use in f_IPv4_enc() */
342 template IPv4_packet ts_IP4(OCT4 srcaddr, OCT4 dstaddr, LIN1 proto, LIN2_BO_LAST tlen, octetstring payload) := {
343 header := {
344 ver := 4,
345 hlen := 5,
346 tos := 0,
347 tlen := tlen,
348 id := 35902,
349 res := '0'B,
350 dfrag := '1'B,
351 mfrag := '0'B,
352 foffset := 0,
353 ttl := 64,
354 proto := proto,
355 cksum := 0,
356 srcaddr := srcaddr,
357 dstaddr := dstaddr
358 },
359 ext_headers := omit,
360 payload := payload
361 }
362
Harald Welte231b9412017-08-09 17:16:31 +0200363 /* template to generate a 'Prefix Information' ICMPv6 option */
364 template OptionField ts_ICMP6_OptPrefix(OCT16 prefix, INT1 prefix_len) := {
365 prefixInformation := {
366 typeField := 3,
367 lengthIndicator := 8,
368 prefixLength := prefix_len,
369 reserved1 := '000000'B,
370 a_Bit := '0'B,
371 l_Bit := '0'B,
372 validLifetime := oct2int('FFFFFFFF'O),
373 preferredLifetime := oct2int('FFFFFFFF'O),
374 reserved2 := '00000000'O,
375 prefix := prefix
376 }
377 }
378
Stefan Sperling6cd217e2018-03-30 15:17:34 +0200379 /* template for sending an ICMPv6 echo request */
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100380 template PDU_ICMPv6 ts_ICMPv6_ERQ := {
381 echoRequest := {
382 typeField := 128,
383 code := 0,
384 checksum := '0000'O,
385 identifier := 0,
386 sequenceNr := 0,
387 data := ''O
388 }
389 }
390
Stefan Sperling6cd217e2018-03-30 15:17:34 +0200391 /* template for sending an ICMPv6 router solicitation */
Harald Welte231b9412017-08-09 17:16:31 +0200392 template PDU_ICMPv6 ts_ICMPv6_RS := {
393 routerSolicitation := {
394 typeField := 133,
395 code := 0,
396 checksum := '0000'O,
397 reserved := '00000000'O,
398 /* TODO: do we need 'Source link-layer address' ? */
399 options := omit
400 }
401 }
402
Stefan Sperling6cd217e2018-03-30 15:17:34 +0200403 /* template for sending an ICMPv6 router advertisement */
Harald Welte231b9412017-08-09 17:16:31 +0200404 template PDU_ICMPv6 ts_ICMPv6_RA(OCT16 prefix, INT1 prefix_len) := {
405 routerAdvertisement := {
406 typeField := 134,
407 code := 0,
408 checksum := '0000'O,
409 curHopLimit := ?,
410 reserved := '000000'B,
411 o_Bit := '0'B,
412 m_Bit := '0'B,
413 routerLifetime := oct2int('FFFF'O),
414 reachableTime := oct2int('FFFFFFFF'O),
415 retransTimer := oct2int('FFFFFFFF'O),
416 options := {
417 ts_ICMP6_OptPrefix(prefix, prefix_len)
418 }
419 }
420 }
421
Stefan Sperling6cd217e2018-03-30 15:17:34 +0200422 /* template for sending an ICMPv6 neighbor solicitation */
Harald Welte231b9412017-08-09 17:16:31 +0200423 template PDU_ICMPv6 ts_ICMPv6_NS(OCT16 target_addr) := {
424 neighborSolicitation := {
425 typeField := 135,
426 code := 0,
427 checksum := '0000'O,
428 reserved := '00000000'O,
429 targetAddress := target_addr,
430 /* TODO: do we need 'Source link-layer address' ? */
431 options := omit
432 }
433 }
434
435 /* derive ICMPv6 link-local address from lower 64bit of link_id */
436 /* template for receiving/matching an ICMPv6 'Prefix Information' option */
437 template OptionField tr_ICMP6_OptPrefix(template OCT16 prefix, template INT1 prefix_len) := {
438 prefixInformation := {
439 typeField := 3,
440 lengthIndicator := 4,
441 prefixLength := prefix_len,
442 reserved1 := ?,
443 a_Bit := ?,
444 l_Bit := ?,
445 validLifetime := ?,
446 preferredLifetime := ?,
447 reserved2 := ?,
448 prefix := prefix
449 }
450 }
451
452 /* template for receiving/matching an ICMPv6 router advertisement */
453 template PDU_ICMPv6 tr_ICMPv6_RA(template OCT16 prefix, template INT1 prefix_len) := {
454 routerAdvertisement := {
455 typeField := 134,
456 code := 0,
457 checksum := ?,
458 curHopLimit := ?,
459 reserved := ?,
460 o_Bit := '0'B,
461 m_Bit := '0'B,
462 routerLifetime := ?,
463 reachableTime := ?,
464 retransTimer := ?,
465 options := {
466 tr_ICMP6_OptPrefix(prefix, prefix_len)
467 }
468 }
469 }
470
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100471 /* template for receiving/matching an ICMPv6 Destination Unreachable */
472 template PDU_ICMPv6 tr_ICMPv6_DU := {
473 destinationUnreachable := {
474 typeField := 1,
475 code := ?,
476 checksum := ?,
477 unused := ?,
478 originalIpMsg := ?
479 }
480 }
481
Stefan Sperling6cd217e2018-03-30 15:17:34 +0200482 /* template for receiving/matching an ICMPv6 echo request */
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +0100483 template PDU_ICMPv6 tr_ICMPv6_ERQ := {
484 echoRequest := {
485 typeField := 128,
486 code := 0,
487 checksum := ?,
488 identifier := ?,
489 sequenceNr := ?,
490 data := ?
491 }
492 }
493
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100494 /* template for receiving/matching an ICMPv6 echo reply */
495 template PDU_ICMPv6 tr_ICMPv6_ERP(template octetstring data := *) := {
496 echoReply := {
497 typeField := 129,
498 code := 0,
499 checksum := ?,
500 identifier := ?,
501 sequenceNr := ?,
502 data := data
503 }
504 }
505
Harald Welte231b9412017-08-09 17:16:31 +0200506 /* template to construct IPv6_packet from input arguments, ready for use in f_IPv6_enc() */
507 template IPv6_packet ts_IP6(OCT16 srcaddr, OCT16 dstaddr, LIN1 nexthead, octetstring payload, LIN1 hlim := 255) := {
508 header := {
509 ver := 6,
510 trclass := 0,
511 flabel := 0,
512 plen := 0,
513 nexthead := nexthead,
514 hlim := hlim,
515 srcaddr := srcaddr,
516 dstaddr := dstaddr
517 },
518 ext_headers := omit,
519 payload := payload
520 }
521
522 function f_ipv6_link_local(in OCT16 link_id) return OCT16 {
523 return 'FE80000000000000'O & substr(link_id, 8, 8);
524 }
525
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100526 function f_ipv6_global(in OCT16 link_id) return OCT16 {
527 return substr(link_id, 0, 8) & '1234123412341234'O;
528 }
529
530 /* Create a new different IPv6 addr from input. Starts mangling at byte prefix. */
531 function f_ipv6_mangle(in OCT16 addr, in integer prefix := 0) return OCT16 {
532 var integer i;
533 var octetstring res := substr(addr, 0, prefix);
534 for (i := prefix; i < lengthof(addr); i := i + 1) {
535 var octetstring a := addr[i] xor4b '11'O;
536 res := res & a;
537 }
538 return res;
539 }
540
Harald Welte231b9412017-08-09 17:16:31 +0200541 /* Compute solicited-node multicast address as per RFC4291 2.7.1 */
542 function f_ipv6_sol_node_mcast(in OCT16 addr) return OCT16 {
543 return 'FF0200000000000000000001FF'O & substr(addr, 13, 3);
544 }
545
546 /* generate and encode ICMPv6 router solicitation */
547 function f_gen_icmpv6_router_solicitation(in OCT16 link_id) return octetstring {
548 const OCT16 c_ip6_all_router_mcast := 'FF020000000000000000000000000002'O;
549 var OCT16 saddr := f_ipv6_link_local(link_id);
550
551 var octetstring tmp;
552 tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_RS), saddr, c_ip6_all_router_mcast);
553 var IPv6_packet ip6 := valueof(ts_IP6(saddr, c_ip6_all_router_mcast, 58, tmp));
554
555 return f_IPv6_enc(ip6);
556 }
557
558 /* create ICMPv6 router solicitation deriving link-id from PDP Context EUA */
559 function f_icmpv6_rs_for_pdp(in PdpContext ctx) return octetstring {
560 var OCT16 interface_id := ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address;
561 return f_gen_icmpv6_router_solicitation(interface_id);
562 }
563
564 /* generate and encode ICMPv6 neighbor solicitation */
565 function f_gen_icmpv6_neigh_solicit(in OCT16 saddr, in OCT16 daddr, in OCT16 tgt_addr) return octetstring {
566 var octetstring tmp;
567 tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_NS(tgt_addr)), saddr, daddr);
568 var IPv6_packet ip6 := valueof(ts_IP6(saddr, daddr, 58, tmp));
569 return f_IPv6_enc(ip6);
570 }
571
572 /* generate and encode ICMPv6 neighbor solicitation for PDP Context */
573 function f_gen_icmpv6_neigh_solicit_for_pdp(in PdpContext ctx) return octetstring {
574 var OCT16 interface_id := ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address;
575 var OCT16 link_local := f_ipv6_link_local(interface_id);
576 var OCT16 daddr := f_ipv6_sol_node_mcast(link_local);
577
578 return f_gen_icmpv6_neigh_solicit(link_local, daddr, link_local);
579 }
580
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100581 /* Send an ICMPv4 echo msg through GTP given pdp ctx, and ip src and dst addr */
582 function f_gen_icmpv4_echo(OCT4 saddr, OCT4 daddr) return octetstring {
583 var octetstring tmp := f_enc_PDU_ICMP(valueof(ts_ICMPv4_ERQ));
584 var IPv4_packet ip4 := valueof(ts_IP4(saddr, daddr, 1, 50, tmp));
585 var octetstring data := f_IPv4_enc(ip4);
586 var OCT2 cksum := f_IPv4_checksum(data);
587 data[10] := cksum[0];
588 data[11] := cksum[1];
589 return data;
590 }
591
592 /* Send an ICMPv6 echo msg through GTP given pdp ctx, and ip src and dst addr */
593 function f_gen_icmpv6_echo(OCT16 saddr, OCT16 daddr) return octetstring {
594 var octetstring tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_ERQ), saddr, daddr);
595 var IPv6_packet ip6 := valueof(ts_IP6(saddr, daddr, 58, tmp));
596 var octetstring data := f_IPv6_enc(ip6);
597 return data;
598 }
599
600 /* Wait for ICMPv4 from GTP */
601 function f_wait_icmp4(PdpContext ctx, template PDU_ICMP expected) runs on GT_CT {
Harald Welte231b9412017-08-09 17:16:31 +0200602 var Gtp1uUnitdata ud;
603 T_default.start;
604 alt {
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100605 [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ?)) -> value ud {
Harald Welte3e0b0392018-04-26 09:46:21 +0200606 if (f_verify_gtpu_txseq(ud.gtpu, use_gtpu_txseq) == false) {
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200607 setverdict(fail);
608 stop;
609 }
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100610 var octetstring gpdu := ud.gtpu.gtpu_IEs.g_PDU_IEs.data;
611 var IPv4_packet ip4 := f_IPv4_dec(gpdu);
612 if (ip4.header.ver != 4) {
613 repeat;
614 }
615 var PDU_ICMP icmp4 := f_dec_PDU_ICMP(ip4.payload);
616 if (not match(icmp4, expected)) {
617 repeat;
618 }
619 }
620 [] GTPU.receive { setverdict(fail); }
621 [] T_default.timeout { setverdict(fail); }
622 }
623 T_default.stop;
624 }
625
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +0100626 /* Wait for ICMPv4 echo request from GTP */
627 function f_wait_icmp4_echo_request(PdpContext ctx) runs on GT_CT {
628 f_wait_icmp4(ctx, tr_ICMPv4_ERQ);
629 }
630
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100631 /* Wait for ICMPv4 echo reply (or unreachable) from GTP */
632 function f_wait_icmp4_echo_reply(PdpContext ctx) runs on GT_CT {
633 f_wait_icmp4(ctx, (tr_ICMPv4_ERP, tr_ICMPv4_DU));
634 }
635
636 /* Wait for ICMPv6 from GTP */
637 function f_wait_icmp6(PdpContext ctx, template PDU_ICMPv6 expected) runs on GT_CT {
638 var Gtp1uUnitdata ud;
639 T_default.start;
640 alt {
Harald Welte231b9412017-08-09 17:16:31 +0200641 [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ?)) -> value ud {
Harald Welte3e0b0392018-04-26 09:46:21 +0200642 if (f_verify_gtpu_txseq(ud.gtpu, use_gtpu_txseq) == false) {
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200643 setverdict(fail);
644 stop;
645 }
Harald Welte231b9412017-08-09 17:16:31 +0200646 var octetstring gpdu := ud.gtpu.gtpu_IEs.g_PDU_IEs.data;
647 var IPv6_packet ip6 := f_IPv6_dec(gpdu);
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100648 if (ip6.header.ver != 6 or ip6.header.nexthead != 58) {
Harald Welte231b9412017-08-09 17:16:31 +0200649 repeat;
650 }
651 var PDU_ICMPv6 icmp6 := f_dec_PDU_ICMPv6(ip6.payload);
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100652 if (not match(icmp6, expected)) {
Harald Welte231b9412017-08-09 17:16:31 +0200653 repeat;
654 }
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100655 /* We are waiting for RA, update ctx */
656 if (match(icmp6, tr_ICMPv6_RA(?, 64))) {
657 ctx.ip6_prefix := icmp6.routerAdvertisement.options[0].prefixInformation.prefix;
658 log("RA with /64 prefix ", ctx.ip6_prefix);
659 }
Harald Welte231b9412017-08-09 17:16:31 +0200660 }
661 [] GTPU.receive(tr_GTPU_GPDU(?, ?)) { repeat; }
662 [] GTPU.receive { setverdict(fail); }
663 [] T_default.timeout { setverdict(fail); }
664 }
665 T_default.stop;
666 }
667
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100668 /* wait for GGSN to send us an ICMPv6 router advertisement */
669 function f_wait_rtr_adv(PdpContext ctx) runs on GT_CT {
670 f_wait_icmp6(ctx, tr_ICMPv6_RA(?, 64));
671 }
672
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +0100673 /* Wait for ICMPv6 echo request from GTP */
674 function f_wait_icmp6_echo_request(PdpContext ctx) runs on GT_CT {
675 f_wait_icmp6(ctx, tr_ICMPv6_ERQ);
676 }
677
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100678 /* Wait for ICMPv6 echo reply (or unreachable) from GTP */
679 function f_wait_icmp6_echo_reply(PdpContext ctx) runs on GT_CT {
680 f_wait_icmp6(ctx, (tr_ICMPv6_ERP,tr_ICMPv6_DU));
681 }
682
683 /* Assert we don't receive a ICMPv4/6 echo reply (or unreachable) from GTP */
684 function f_wait_gtpu_fail(PdpContext ctx) runs on GT_CT {
685 T_default.start;
686 alt {
687 [] GTPU.receive { setverdict(fail); }
688 [] T_default.timeout { }
689 }
690 T_default.stop;
691 }
692
Harald Welte0ef285b2017-08-13 20:06:01 +0200693 /* Test IPv6 context activation for dynamic IPv6 EUA without request of IPv6 DNS */
Harald Welteed7a1772017-08-09 20:26:20 +0200694 testcase TC_pdp6_act_deact() runs on GT_CT {
Harald Welte94ade362017-08-04 00:36:55 +0200695 f_init();
Harald Welte231b9412017-08-09 17:16:31 +0200696
Harald Welteed097432017-08-13 13:28:49 +0200697 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Harald Welte811651e2017-08-05 15:25:06 +0200698 f_pdp_ctx_act(ctx);
Harald Welteed7a1772017-08-09 20:26:20 +0200699 f_pdp_ctx_del(ctx, '1'B);
700 }
701
Harald Welte0ef285b2017-08-13 20:06:01 +0200702 /* Test IPv6 context activation for dynamic IPv6 EUA wirh request of IPv6 DNS in PCO */
Harald Welteed7a1772017-08-09 20:26:20 +0200703 testcase TC_pdp6_act_deact_pcodns() runs on GT_CT {
704 f_init();
705
Harald Welteed097432017-08-13 13:28:49 +0200706 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Harald Welteed7a1772017-08-09 20:26:20 +0200707 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
708 f_pdp_ctx_act(ctx);
Pau Espin Pedrol363ba482018-01-29 18:42:00 +0100709
710 /* verify PCO contains both primary and secondary DNS */
711 var OCT4 ggsn_ip6_dns1 := f_inet6_addr(m_ggsn_ip6_dns1);
712 if (not match(f_PCO_extract_proto(ctx.pco_neg, '0003'O, 1), ggsn_ip6_dns1)) {
713 setverdict(fail, "Primary DNS IPv6 PCO option not found");
714 }
715
716 var OCT4 ggsn_ip6_dns2 := f_inet6_addr(m_ggsn_ip6_dns2);
717 if (not match(f_PCO_extract_proto(ctx.pco_neg, '0003'O, 2), ggsn_ip6_dns2)) {
718 setverdict(fail, "Secondary DNS IPv6 PCO option not found");
719 }
720
Harald Welteed7a1772017-08-09 20:26:20 +0200721 f_pdp_ctx_del(ctx, '1'B);
722 }
723
Harald Welte0ef285b2017-08-13 20:06:01 +0200724 /* Test PDP context activation for dynamic IPv6 EUA with IPv6 DNS in PCO and router solicitation/advertisement */
Harald Welteed7a1772017-08-09 20:26:20 +0200725 testcase TC_pdp6_act_deact_icmp6() runs on GT_CT {
726 f_init();
727
Harald Welteed097432017-08-13 13:28:49 +0200728 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Harald Welteed7a1772017-08-09 20:26:20 +0200729 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
730 f_pdp_ctx_act(ctx);
Harald Welte231b9412017-08-09 17:16:31 +0200731
732 //f_send_gtpu(ctx, c_router_solicit);
733 //f_send_gtpu(ctx, c_neigh_solicit);
734
735 f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
736 f_wait_rtr_adv(ctx);
737 f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
738
Harald Welte811651e2017-08-05 15:25:06 +0200739 f_pdp_ctx_del(ctx, '1'B);
Harald Welte94ade362017-08-04 00:36:55 +0200740 }
741
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100742 /* Test PDP context activation for dynamic IPv6 EUA with IPv6 DNS in PCO and router solicitation/advertisement.
743 Test we can send ICMPv6 ping over GTPU to DNS server. */
744 testcase TC_pdp6_act_deact_gtpu_access() runs on GT_CT {
745 f_init();
746 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
747 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
748 f_pdp_ctx_act(ctx);
749
750 f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
751 f_wait_rtr_adv(ctx);
752 f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
753
754 var OCT16 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '0003'O);
755
756 /* Check if we can use valid link-local src addr. */
757 var OCT16 saddr_ll := f_ipv6_link_local(ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
758 f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_ll, dns1_addr));
759 f_wait_icmp6_echo_reply(ctx);
760
761 /* Check that attempting RA with another ll src addr won't work, packet dropped: */
762 var OCT16 saddr_ll_wrong := f_ipv6_mangle(saddr_ll, 8);
763 f_send_gtpu(ctx, f_gen_icmpv6_router_solicitation(saddr_ll_wrong));
764 f_wait_gtpu_fail(ctx);
765
766 /* Check if we can use valid global src addr, should work */
767 var OCT16 saddr_glob := f_ipv6_global(ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
768 f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_glob, dns1_addr));
769 f_wait_icmp6_echo_reply(ctx);
770
771 /* Assert that packets with wrong global src addr are dropped by GGSN */
772 var OCT16 saddr_wrong := f_ipv6_mangle(saddr_glob);
773 f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_wrong, dns1_addr));
774 f_wait_gtpu_fail(ctx);
775
776 /* Send an IPv4 ICMP ECHO REQUEST to APN6, should fail (packet dropped) */
777 var OCT4 saddr_v4 := f_inet_addr("192.168.10.2");
778 var OCT4 daddr_v4 := f_inet_addr("8.8.8.8");
779 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr_v4, daddr_v4));
780 f_wait_gtpu_fail(ctx);
781
782 f_pdp_ctx_del(ctx, '1'B);
783 }
784
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +0100785 /* Validate if different clients (pdp ctx) can reach one another through GGSN. */
786 testcase TC_pdp6_clients_interact() runs on GT_CT {
787 f_init();
788 var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
789 var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
790 f_pdp_ctx_act(ctxA);
791 f_send_gtpu(ctxA, f_icmpv6_rs_for_pdp(ctxA));
792 f_wait_rtr_adv(ctxA);
793 f_send_gtpu(ctxA, f_gen_icmpv6_neigh_solicit_for_pdp(ctxA));
794
795 f_pdp_ctx_act(ctxB);
796 f_send_gtpu(ctxB, f_icmpv6_rs_for_pdp(ctxB));
797 f_wait_rtr_adv(ctxB);
798 f_send_gtpu(ctxB, f_gen_icmpv6_neigh_solicit_for_pdp(ctxB));
799
800 var OCT16 addrA_ll := f_ipv6_link_local(ctxA.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
801 var OCT16 addrB_ll := f_ipv6_link_local(ctxB.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
802 var OCT16 addrA_glob := f_ipv6_global(ctxA.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
803 var OCT16 addrB_glob := f_ipv6_global(ctxB.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
804
805 /* Validate if clients can interact using ll addr. */
806 f_send_gtpu(ctxA, f_gen_icmpv6_echo(addrA_ll, addrB_ll));
807 f_wait_gtpu_fail(ctxB);
808
809 /* Validate if clients can interact using global addr. */
810 f_send_gtpu(ctxA, f_gen_icmpv6_echo(addrA_glob, addrB_glob));
811 f_wait_gtpu_fail(ctxB);
812
813 f_pdp_ctx_del(ctxA, '1'B);
814 }
815
Harald Welte0ef285b2017-08-13 20:06:01 +0200816 /* Test PDP context activation for dynamic IPv4 EUA without DNS request */
Harald Welteed7a1772017-08-09 20:26:20 +0200817 testcase TC_pdp4_act_deact() runs on GT_CT {
818 f_init();
Harald Welteed097432017-08-13 13:28:49 +0200819 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Harald Welteed7a1772017-08-09 20:26:20 +0200820 f_pdp_ctx_act(ctx);
821 f_pdp_ctx_del(ctx, '1'B);
822 }
823
Harald Welte0ef285b2017-08-13 20:06:01 +0200824 /* Test PDP context activation for dynamic IPv4 EUA with IPv4 DNS in IPCP */
Harald Welteed7a1772017-08-09 20:26:20 +0200825 testcase TC_pdp4_act_deact_ipcp() runs on GT_CT {
826 f_init();
Pau Espin Pedrolf69a4382018-01-29 13:09:00 +0100827 var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
828 var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
Harald Welteed097432017-08-13 13:28:49 +0200829 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Harald Weltedca80052017-08-13 20:01:38 +0200830 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_IPCP);
Harald Welteed7a1772017-08-09 20:26:20 +0200831 f_pdp_ctx_act(ctx);
Harald Welte71a36022017-12-04 18:55:58 +0100832 /* verify IPCP is at all contained */
833 if (not match(ctx.pco_neg, tr_PCO_Contains('8021'O))) {
834 setverdict(fail, "IPCP not found in PCO");
835 }
836 /* verify IPCP contains both primary and secondary DNS */
837 var IpcpPacket ipcp := dec_IpcpPacket(f_PCO_extract_proto(ctx.pco_neg, '8021'O));
Pau Espin Pedrolf69a4382018-01-29 13:09:00 +0100838 if (not match(ipcp, tr_IPCP_Ack_DNS(0, ggsn_ip4_dns1, ggsn_ip4_dns2))) {
839 if (not match(ipcp, tr_IPCP_Ack_DNS(0))) {
840 setverdict(fail, "Primary/Secondary DNS PCO IPCP option not found");
841 } else {
842 setverdict(fail, "Primary/Secondary DNS PCO IPCP option found but not matching expected values");
843 }
Harald Welte71a36022017-12-04 18:55:58 +0100844 }
Harald Welteed7a1772017-08-09 20:26:20 +0200845 f_pdp_ctx_del(ctx, '1'B);
846 }
847
Harald Welte0ef285b2017-08-13 20:06:01 +0200848 /* Test PDP context activation for dynamic IPv4 EUA with IPv4 DNS in PCO */
Harald Welteed7a1772017-08-09 20:26:20 +0200849 testcase TC_pdp4_act_deact_pcodns() runs on GT_CT {
850 f_init();
Harald Welteed097432017-08-13 13:28:49 +0200851 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Harald Weltedca80052017-08-13 20:01:38 +0200852 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
Harald Welteed7a1772017-08-09 20:26:20 +0200853 f_pdp_ctx_act(ctx);
Pau Espin Pedrol363ba482018-01-29 18:42:00 +0100854
855 /* verify PCO contains both primary and secondary DNS */
856 var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
857 if (not match(f_PCO_extract_proto(ctx.pco_neg, '000d'O, 1), ggsn_ip4_dns1)) {
858 setverdict(fail, "Primary DNS IPv4 PCO option not found");
859 }
860
861 var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
862 if (not match(f_PCO_extract_proto(ctx.pco_neg, '000d'O, 2), ggsn_ip4_dns2)) {
863 setverdict(fail, "Secondary DNS IPv4 PCO option not found");
864 }
865
Harald Welteed7a1772017-08-09 20:26:20 +0200866 f_pdp_ctx_del(ctx, '1'B);
867 }
868
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100869 /* Test PDP context activation for dynamic IPv4 EUA.
870 Test we can send ICMPv6 ping over GTPU to DNS server. */
871 testcase TC_pdp4_act_deact_gtpu_access() runs on GT_CT {
872 f_init();
873 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
874 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
875 f_pdp_ctx_act(ctx);
876
877 var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O);
878
879 /* Check if we can use valid global src addr, should work */
880 var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
881 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
882 f_wait_icmp4_echo_reply(ctx);
883
884 /* Assert that packets with wrong global src addr are dropped by GGSN */
885 var OCT4 saddr_wrong := substr(saddr, 0, 3) & (saddr[3] xor4b '11'O);
886 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr_wrong, dns1_addr));
887 f_wait_gtpu_fail(ctx);
888
889 /* Send an IPv6 RA to APN4, should fail (packet dropped) */
890 var OCT16 saddr_v6 := f_inet6_addr("fde4:8dba:82e1:2000:1:2:3:4");
891 f_send_gtpu(ctx, f_gen_icmpv6_router_solicitation(saddr_v6));
892 f_wait_gtpu_fail(ctx);
893 f_pdp_ctx_del(ctx, '1'B);
894 }
895
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200896 /* Helper function for tests below. */
897 function f_pdp4_clients_interact() runs on GT_CT {
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +0100898 f_init();
899 var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
900 var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
901 f_pdp_ctx_act(ctxA);
902 f_pdp_ctx_act(ctxB);
903 var OCT4 addrA := ctxA.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
904 var OCT4 addrB := ctxB.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
905 f_send_gtpu(ctxA, f_gen_icmpv4_echo(addrA, addrB));
906 f_wait_icmp4_echo_request(ctxB);
907
908 f_pdp_ctx_del(ctxA, '1'B);
909 }
910
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200911 /* Validate if different clients (pdp ctx) can reach one another through GGSN. */
912 testcase TC_pdp4_clients_interact_with_txseq() runs on GT_CT {
Harald Welte3e0b0392018-04-26 09:46:21 +0200913 use_gtpu_txseq := true;
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200914 f_pdp4_clients_interact();
915 }
916
917 /* Validate if different clients (pdp ctx) can reach one another through GGSN (without Tx sequence number). */
918 testcase TC_pdp4_clients_interact_without_txseq() runs on GT_CT {
Harald Welte3e0b0392018-04-26 09:46:21 +0200919 use_gtpu_txseq := false;
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200920 f_pdp4_clients_interact();
921 }
922
Harald Weltedca80052017-08-13 20:01:38 +0200923 testcase TC_echo_req_resp() runs on GT_CT {
924 f_init();
925 f_send_gtpc(ts_GTPC_PING(g_peer_c, g_c_seq_nr));
926 T_default.start;
927 alt {
928 [] GTPC.receive(tr_GTPC_PONG(g_peer_c)) { setverdict(pass); };
929 [] GTPC.receive { repeat; };
930 [] T_default.timeout { setverdict(fail); }
931 }
932 T_default.stop;
933 }
934
Philipp Maier33e52612018-05-30 17:22:02 +0200935 /* Test if the parser can cope with PCO that only contain either a
936 * single primary DNS or a secondary DNS. */
937 testcase TC_pdp4_act_deact_with_single_dns() runs on GT_CT {
938
939 /* Note: an unpatched osmo-ggsn version will enter an endless-loop when
940 * the test is executed.
941 * see also: Change-Id Icffde89f9bc5d8fcadf6e2dd6c0b4de03440edd5 and OS#3288 */
942
943 f_init();
944 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
945 var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
946 var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
947 var octetstring pco_neg_dns;
948 var octetstring pco_neg_dns_expected;
949
950 /* PCO with primary DNS only */
951 ctx.pco_req := valueof(ts_PCO_IPv4_PRI_DNS_IPCP);
952 f_pdp_ctx_act(ctx);
953 pco_neg_dns := f_PCO_extract_proto(ctx.pco_neg, '8021'O, 1);
954 pco_neg_dns_expected := '0200000A8106'O & ggsn_ip4_dns1
955 /* Note: The prepended hex bytes encode the following information:
956 * 0x02 = Configuration ACK
957 * 0x00 = Identifier
958 * 0x000a = Length
959 * 0x81 = Type (Primary DNS Server Address)
960 * 0x06 = Length
961 * (4 byte IP-Address appended) */
962 if (not match(pco_neg_dns, pco_neg_dns_expected)) {
963 setverdict(fail, "Primary DNS IPv4 PCO option not found");
964 }
965 f_pdp_ctx_del(ctx, '1'B);
966
967 /* PCO with secondary DNS only */
968 ctx.pco_req := valueof(ts_PCO_IPv4_SEC_DNS_IPCP);
969 f_pdp_ctx_act(ctx);
970 pco_neg_dns := f_PCO_extract_proto(ctx.pco_neg, '8021'O, 1);
971 pco_neg_dns_expected := '0200000A8306'O & ggsn_ip4_dns2
972 if (not match(pco_neg_dns, pco_neg_dns_expected)) {
973 setverdict(fail, "Secondary DNS IPv4 PCO option not found");
974 }
975 f_pdp_ctx_del(ctx, '1'B);
976 }
977
978 /* Test if the parser can cope with PCO that contains primary and secondary DNS in a separate IPCP container.
979 * Note: an unpatched osmo-ggsn version will enter an endless-loop when the test is run
980 * see Change-Id Icffde89f9bc5d8fcadf6e2dd6c0b4de03440edd5 and OS#3288. */
981 testcase TC_pdp4_act_deact_with_separate_dns() runs on GT_CT {
982
983 /* Note: an unpatched osmo-ggsn version will enter an endless-loop when
984 * the test is executed.
985 * see also: Change-Id Icffde89f9bc5d8fcadf6e2dd6c0b4de03440edd5 and OS#3288 */
986
987 f_init();
988 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
989 var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
990 var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
991 var octetstring pco_neg_dns;
992 var octetstring pco_neg_dns_expected;
993
994 ctx.pco_req := valueof(ts_PCO_IPv4_SEPARATE_DNS_IPCP);
995 f_pdp_ctx_act(ctx);
996
997 /* Check if primary DNS is contained */
998 pco_neg_dns := f_PCO_extract_proto(ctx.pco_neg, '8021'O, 1);
999 pco_neg_dns_expected := '0200000A8106'O & ggsn_ip4_dns1
1000 if (not match(pco_neg_dns, pco_neg_dns_expected)) {
1001 setverdict(fail, "Primary DNS IPv4 PCO option not found");
1002 }
1003 f_pdp_ctx_del(ctx, '1'B);
1004
1005 /* Check if secondary DNS is contained */
1006 /* Note: this check fill fail due to a bug in osmo-ggsn, see also OS#3381 */
1007 pco_neg_dns := f_PCO_extract_proto(ctx.pco_neg, '8021'O, 1);
1008 pco_neg_dns_expected := '0200000A8306'O & ggsn_ip4_dns2
1009 if (not match(pco_neg_dns, pco_neg_dns_expected)) {
1010 setverdict(fail, "Secondary DNS IPv4 PCO option not found");
1011 }
1012 f_pdp_ctx_del(ctx, '1'B);
1013 }
1014
Harald Welte94ade362017-08-04 00:36:55 +02001015 control {
Harald Welteed7a1772017-08-09 20:26:20 +02001016 execute(TC_pdp4_act_deact());
1017 execute(TC_pdp4_act_deact_ipcp());
1018 execute(TC_pdp4_act_deact_pcodns());
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001019 execute(TC_pdp4_act_deact_gtpu_access());
Stefan Sperlingc479e4f2018-04-03 19:34:16 +02001020 execute(TC_pdp4_clients_interact_with_txseq());
1021 execute(TC_pdp4_clients_interact_without_txseq());
Philipp Maier33e52612018-05-30 17:22:02 +02001022 execute(TC_pdp4_act_deact_with_single_dns());
1023 execute(TC_pdp4_act_deact_with_separate_dns());
Harald Welteed7a1772017-08-09 20:26:20 +02001024
1025 execute(TC_pdp6_act_deact());
1026 execute(TC_pdp6_act_deact_pcodns());
1027 execute(TC_pdp6_act_deact_icmp6());
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001028 execute(TC_pdp6_act_deact_gtpu_access());
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +01001029 execute(TC_pdp6_clients_interact());
Harald Weltedca80052017-08-13 20:01:38 +02001030
1031 execute(TC_echo_req_resp());
Harald Welte94ade362017-08-04 00:36:55 +02001032 }
Harald Welte379d45a2017-08-03 09:55:15 +02001033}