aboutsummaryrefslogtreecommitdiffstats
path: root/dia2gsup/DIA2GSUP_Tests.ttcn
blob: 6a3f85c895155b1dc443666e9bd7610149721e4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
module DIA2GSUP_Tests {

import from Misc_Helpers all;
import from General_Types all;
import from Osmocom_Types all;
import from L3_Common all;

import from IPA_Emulation all;
import from GSUP_Emulation all;
import from GSUP_Types all;

import from DIAMETER_Types all;
import from DIAMETER_Templates all;
import from DIAMETER_Emulation all;

type component MTC_CT {
	var DIAMETER_Emulation_CT vc_DIAMETER;
	port DIAMETER_PT DIAMETER_UNIT;
	port DIAMETEREM_PROC_PT DIAMETER_PROC;

	var GSUP_Emulation_CT vc_GSUP;
	var IPA_Emulation_CT vc_GSUP_IPA;
	port IPA_CTRL_PT GSUP_IPA_EVENT;

	timer g_Tguard;
};

type component D2G_ConnHdlr extends DIAMETER_ConnHdlr, GSUP_ConnHdlr {
	var D2G_ConnHdlrPars g_pars;
};

type record D2G_ConnHdlrPars {
	hexstring imsi,
	AuthVector vec optional
};

private function f_init_pars(integer imsi_suffix := 1)
runs on MTC_CT return D2G_ConnHdlrPars {
	var D2G_ConnHdlrPars pars := {
		imsi := f_gen_imsi(imsi_suffix),
		vec := f_gen_auth_vec_3g()
	};
	return pars;
}


modulepar {
	/* our emulated GSUP HLR */
	charstring mp_hlr_ip := "127.0.0.1";
	integer mp_hlr_port := 4222;

	/* our emulated MME */
	charstring mp_s6_local_ip := "127.0.0.100";
	integer mp_s6_local_port := 3868;

	/* IUT behaving as HSS */
	charstring mp_hss_ip := "127.0.0.4";
	integer mp_hss_port := 3868;

	charstring mp_diam_realm := "localdomain";
}

private altstep as_Tguard() runs on MTC_CT {
	[] g_Tguard.timeout {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Tguard timeout");
	}
}

private function f_init_gsup(charstring id) runs on MTC_CT {
	id := id & "-GSUP";
	var GsupOps ops := {
		create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
	};

	vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
	vc_GSUP := GSUP_Emulation_CT.create(id);

	map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
	connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
	/* we use this hack to get events like ASP_IPA_EVENT_UP */
	connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);

	vc_GSUP.start(GSUP_Emulation.main(ops, id));
	vc_GSUP_IPA.start(IPA_Emulation.main_server(mp_hlr_ip, mp_hlr_port));

	/* wait for incoming connection to GSUP port before proceeding */
	timer T := 10.0;
	T.start;
	alt {
	[] GSUP_IPA_EVENT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) { }
	[] T.timeout {
		setverdict(fail, "No connection to GSUP Port");
		mtc.stop;
		}
	}
}

private type function void_fn(charstring id) runs on D2G_ConnHdlr;

private function f_init_handler(void_fn fn, charstring id, D2G_ConnHdlrPars pars) runs on D2G_ConnHdlr {
	g_pars := pars;

	/* tell GSUP dispatcher to send this IMSI to us */
	f_create_gsup_expect(hex2str(g_pars.imsi));

	fn.apply(id);
}

private function f_start_handler(void_fn fn, D2G_ConnHdlrPars pars)
runs on MTC_CT return D2G_ConnHdlr {
	var D2G_ConnHdlr vc_conn;
	var charstring id := testcasename();

	vc_conn := D2G_ConnHdlr.create(id);

	connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
	connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);

	connect(vc_conn:DIAMETER, vc_DIAMETER:DIAMETER_CLIENT);
	connect(vc_conn:DIAMETER_PROC, vc_DIAMETER:DIAMETER_PROC);

	DIAMETER_UNIT.receive(DiameterCapabilityExchgInd:?);

	vc_conn.start(f_init_handler(fn, id, pars));
	return vc_conn;
}

private function DiameterForwardUnitdataCallback(PDU_DIAMETER msg)
runs on DIAMETER_Emulation_CT return template PDU_DIAMETER {
	DIAMETER_UNIT.send(msg);
	return omit;
}

private function f_init_diameter(charstring id) runs on MTC_CT {
	var DIAMETEROps ops := {
		create_cb := refers(DIAMETER_Emulation.ExpectedCreateCallback),
		unitdata_cb := refers(DiameterForwardUnitdataCallback),
		raw := false /* handler mode (IMSI based routing) */
	};
	var DIAMETER_conn_parameters pars := {
		remote_ip := mp_hss_ip,
		remote_sctp_port := mp_hss_port,
		local_ip := mp_s6_local_ip,
		local_sctp_port := mp_s6_local_port,
		origin_host := "hss." & mp_diam_realm,
		origin_realm := mp_diam_realm,
		auth_app_id := omit,
		vendor_app_id := c_DIAMETER_3GPP_S6_AID
	};
	vc_DIAMETER := DIAMETER_Emulation_CT.create(id);
	map(vc_DIAMETER:DIAMETER, system:DIAMETER_CODEC_PT);
	connect(vc_DIAMETER:DIAMETER_UNIT, self:DIAMETER_UNIT);
	connect(vc_DIAMETER:DIAMETER_PROC, self:DIAMETER_PROC);
	vc_DIAMETER.start(DIAMETER_Emulation.main(ops, pars, id));
}

private function f_init(float t_guard := 40.0) runs on MTC_CT {

	g_Tguard.start(t_guard);
	activate(as_Tguard());

	f_init_gsup(testcasename());
	f_init_diameter(testcasename());
}


private function f_DIA_AI_success() runs on D2G_ConnHdlr {
	var PDU_DIAMETER rx_dia;
	var UINT32 hbh_id := f_rnd_octstring(4);
	var UINT32 ete_id := f_rnd_octstring(4);
	var octetstring sess_id := char2oct("foobar");
	var OCT3 vplmn := '00F110'O;

	/* Unlike AIR, AIA contains no IMSI. Register ete_id in DIAMETER_Emulation,
	 * so AIA is forwarded back to us in DIAMETER port instead of MTC_CT.DIAMETER_UNIT.
	 */
	f_diameter_expect_eteid(ete_id);

	/* Send AIR to translator; expect it to show up on GSUP side */
	DIAMETER.send(ts_DIA_AIR(g_pars.imsi, vplmn, sess_id, hbh_id := hbh_id, ete_id := ete_id));
	GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));

	/* Send a positive response back to the translator; expect AIA */
	var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G3G(g_pars.vec.rand,
								   g_pars.vec.sres,
								   g_pars.vec.kc,
								   g_pars.vec.ik,
								   g_pars.vec.ck,
								   g_pars.vec.autn,
								   g_pars.vec.res));
	GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));

	alt {
	/* Unlike AIR, AIA contains no IMSI, hence it is received in DIAMETER_UNIT: */
	[] DIAMETER.receive(tr_DIA_AIA) {
		setverdict(pass);
		}
	[] DIAMETER.receive(PDU_DIAMETER:?) -> value rx_dia {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected Diameter msg rx: ", rx_dia));
		}
	}
}

private function f_TC_authinfo_normal(charstring id) runs on D2G_ConnHdlr {
	f_DIA_AI_success();
}

testcase TC_authinfo_normal() runs on MTC_CT {
	var D2G_ConnHdlrPars pars := f_init_pars();
	var D2G_ConnHdlr vc_conn;
	f_init();
	vc_conn := f_start_handler(refers(f_TC_authinfo_normal), pars);
	vc_conn.done;
	setverdict(pass);
}

control {
	execute ( TC_authinfo_normal() );
}

}