blob: d1e31855b2558630413f34ed7e0587f16acf3e12 [file] [log] [blame]
Pau Espin Pedrolac8a0542024-04-19 17:30:57 +02001/* Component implementing a IMS server towards Asterisk's IMS UE
2 * (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
3 * Author: Pau Espin Pedrol <pespin@sysmocom.de>
4 * All rights reserved.
5 *
6 * Released under the terms of GNU General Public License, Version 2 or
7 * (at your option) any later version.
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11module IMS_ConnectionHandler {
12
Pau Espin Pedrol717379f2024-05-17 18:36:51 +020013import from TCCEncoding_Functions all;
Pau Espin Pedrolac8a0542024-04-19 17:30:57 +020014import from TCCOpenSecurity_Functions all;
15import from General_Types all;
16import from Osmocom_Types all;
17import from Native_Functions all;
18import from Misc_Helpers all;
19
Pau Espin Pedrola674d612024-05-14 19:56:33 +020020/* the PIPE asp port allows us to interact with ip xfrm via stdin/stdout */
21import from PIPEasp_PortType all;
22import from PIPEasp_Types all;
23import from PIPEasp_Templates all;
24
Pau Espin Pedrolac8a0542024-04-19 17:30:57 +020025import from SDP_Types all;
26import from SDP_Templates all;
27
28import from SIP_Emulation all;
29import from SIPmsg_Types all;
30import from SIP_Templates all;
31
Pau Espin Pedrola674d612024-05-14 19:56:33 +020032
33modulepar {
34 charstring mp_ipsec_setup_script_path := "./IMS_ipsec_setup.sh";
35}
36
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +020037const char c_sip_server_name := "osmo-ttcn3-hacks/0.23";
38
39
Pau Espin Pedrolac8a0542024-04-19 17:30:57 +020040type port IMSCoord_PT message
41{
42 inout charstring;
43} with { extension "internal" };
44
45const charstring IMS_COORD_CMD_REGISTERED := "COORD_CMD_REGISTERED";
46
47type component IMS_ConnHdlr extends SIP_ConnHdlr {
48 var charstring g_name;
49 var IMS_ConnHdlrPars g_pars;
50 timer g_Tguard;
51 var PDU_SIP_Request g_rx_sip_req;
52 var PDU_SIP_Response g_rx_sip_resp;
53
54 port IMSCoord_PT COORD;
Pau Espin Pedrola674d612024-05-14 19:56:33 +020055 port PIPEasp_PT PIPE;
Pau Espin Pedrolac8a0542024-04-19 17:30:57 +020056}
57type record of IMS_ConnHdlr IMS_ConnHdlrList;
58
59type record IMS_ConnHdlrPars {
60 float t_guard,
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +020061 charstring realm,
62 charstring local_sip_host,
63 uint16_t local_sip_port,
64 charstring remote_sip_host optional,
65 uint16_t remote_sip_port optional,
Pau Espin Pedrolac8a0542024-04-19 17:30:57 +020066 charstring user,
67 charstring display_name,
68 charstring password,
Pau Espin Pedrol717379f2024-05-17 18:36:51 +020069 octetstring rand,
70 octetstring autn,
Pau Espin Pedrola674d612024-05-14 19:56:33 +020071 charstring ipsec_auth_key,
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +020072 integer ipsec_local_spi_c,
73 integer ipsec_local_spi_s,
74 integer ipsec_remote_spi_c optional,
75 integer ipsec_remote_spi_s optional,
Pau Espin Pedrola674d612024-05-14 19:56:33 +020076 uint16_t ipsec_remote_port_c optional,
77 uint16_t ipsec_remote_port_s optional,
Pau Espin Pedrolac8a0542024-04-19 17:30:57 +020078 SipUrl registrar_sip_req_uri,
79 SipAddr registrar_sip_record,
80 CallidString registrar_sip_call_id,
81 integer registrar_sip_seq_nr,
82 Via local_via,
83 SipUrl local_sip_url_ext,
84 SipAddr local_sip_record,
85 Contact local_contact,
86 IMS_CallPars cp optional
87}
88type record of IMS_ConnHdlrPars IMS_ConnHdlrParsList;
89
90type record IMS_CallParsMT {
91 /* Whether to wait for COORD.receive(COORD_CMD_PICKUP) before accepting the call. */
92 boolean wait_coord_cmd_pickup,
93 /* Whether to expect CANCEL instead of ACK as answer to our OK */
94 boolean exp_cancel
95}
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +020096template (value) IMS_CallParsMT t_IMS_CallParsMT := {
97 wait_coord_cmd_pickup := false,
98 exp_cancel := false
99}
Pau Espin Pedrolac8a0542024-04-19 17:30:57 +0200100
101type record IMS_CallPars {
102 SipAddr calling optional,
103 SipAddr called optional,
104
105 SipAddr from_addr optional,
106 SipAddr to_addr optional,
107
108 CallidString sip_call_id,
109 integer sip_seq_nr,
110 charstring sip_body optional,
111
112 charstring local_rtp_addr,
113 uint16_t local_rtp_port,
114
115 SDP_Message peer_sdp optional,
116 IMS_CallParsMT mt
117}
118
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200119template (value) IMS_CallPars t_IMS_CallPars(charstring local_rtp_addr,
120 uint16_t local_rtp_port := 0,
121 template (omit) SipAddr calling := omit,
122 template (omit) SipAddr called := omit) := {
123 calling := calling,
124 called := called,
125 from_addr := omit,
126 to_addr := omit,
127 sip_call_id := hex2str(f_rnd_hexstring(15)),
128 sip_seq_nr := f_sip_rand_seq_nr(),
129 sip_body := omit,
130 local_rtp_addr := local_rtp_addr,
131 local_rtp_port := local_rtp_port,
132 peer_sdp := omit,
133 mt := t_IMS_CallParsMT
134}
135
136template (value) IMS_ConnHdlrPars t_IMS_Pars(charstring local_sip_host,
137 uint16_t local_sip_port,
138 charstring user,
139 charstring display_name := "Anonymous",
140 charstring password := "secret",
141 template (omit) IMS_CallPars cp := omit) := {
142 t_guard := 30.0,
143 realm := local_sip_host,
144 local_sip_host := local_sip_host,
145 local_sip_port := local_sip_port,
146 remote_sip_host := omit,
147 remote_sip_port := omit,
148 user := user,
149 display_name := f_sip_str_quote(display_name),
150 password := password,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200151 /* The Nonce field is the Base64 encoded version of the RAND value and concatenated with the AUTN: */
Pau Espin Pedrol717379f2024-05-17 18:36:51 +0200152 rand := '14987631f65f8e3788a0798b6ebcd08e'O,
153 autn := 'f6e19a7ccb028000a06b19c9544516e5'O,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200154 ipsec_auth_key := "0x5238297dfcca759bd05d48ff49bc63fa00000000",
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200155 ipsec_local_spi_c := 4142,
156 ipsec_local_spi_s := 4143,
157 ipsec_remote_spi_c := omit,
158 ipsec_remote_spi_s := omit,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200159 ipsec_remote_port_c := omit,
160 ipsec_remote_port_s := omit,
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200161 registrar_sip_req_uri := valueof(ts_SipUrlHost(local_sip_host)),
162 registrar_sip_record := ts_SipAddr(ts_HostPort(local_sip_host),
163 ts_UserInfo(user),
164 f_sip_str_quote(display_name)),
165 registrar_sip_call_id := hex2str(f_rnd_hexstring(15)) & "@" & local_sip_host,
166 registrar_sip_seq_nr := f_sip_rand_seq_nr(),
167 local_via := ts_Via_from(ts_HostPort(local_sip_host, local_sip_port)),
168 local_sip_url_ext := ts_SipUrl(ts_HostPort(local_sip_host, local_sip_port),
169 ts_UserInfo(user)),
170 local_sip_record := ts_SipAddr(ts_HostPort(local_sip_host),
171 ts_UserInfo(user)),
172 local_contact := valueof(ts_Contact({
173 ts_ContactAddress(
174 ts_Addr_Union_SipUrl(ts_SipUrl(ts_HostPort(
175 local_sip_host,
176 local_sip_port),
177 ts_UserInfo(user))),
178 omit)
179 })),
180 cp := cp
181}
182
183private altstep as_Tguard() runs on IMS_ConnHdlr {
184 [] g_Tguard.timeout {
185 setverdict(fail, "Tguard timeout");
186 mtc.stop;
187 }
188}
189
190type function ims_void_fn(charstring id) runs on IMS_ConnHdlr;
191function f_ims_handler_init(ims_void_fn fn, charstring id, IMS_ConnHdlrPars pars)
192runs on IMS_ConnHdlr {
193 g_name := id;
194 g_pars := pars;
195 g_Tguard.start(pars.t_guard);
196 activate(as_Tguard());
197
198 /* call the user-supied test case function */
199 fn.apply(id);
200}
201
202private altstep as_SIP_fail_req(charstring exp_msg_str := "") runs on IMS_ConnHdlr
203{
204 var PDU_SIP_Request sip_req;
205 [] SIP.receive(PDU_SIP_Request:?) -> value sip_req {
206 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
207 log2str(g_name & ": Received unexpected SIP Req message := ", sip_req, "\nvs exp := ", exp_msg_str));
208 }
209}
210
211private altstep as_SIP_fail_resp(charstring exp_msg_str := "") runs on IMS_ConnHdlr
212{
213 var PDU_SIP_Response sip_resp;
214 [] SIP.receive(PDU_SIP_Response:?) -> value sip_resp {
215 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
216 log2str(g_name & ": Received unexpected SIP Resp message := ", sip_resp, "\nvs exp := ", exp_msg_str));
217 }
218}
219
Pau Espin Pedrol717379f2024-05-17 18:36:51 +0200220private function f_nonce_from_rand_autn(octetstring rand, octetstring autn) return charstring {
221 var octetstring concat := rand & autn;
222 var charstring nonce := enc_MIME_Base64(concat);
223 log("rand=", rand, " & autn=",autn, " => nonce=", nonce);
224 return nonce;
225}
226
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200227/* HTTP Digest Authentication Using AKA (AKAv1-MD5): RFC 3310 */
228function f_tr_Authorization_AKAv1MD5(WwwAuthenticate www_authenticate,
229 charstring username,
230 charstring uri,
231 integer nc_int := 1)
232return template (present) Authorization {
233 var CommaParam_List digestCln;
234 var template (present) Authorization authorization;
235 var template (present) Credentials cred;
236 var template (omit) GenericParam rx_param;
237
238 digestCln := www_authenticate.challenge[0].digestCln;
239
240 var charstring algorithm := f_sip_param_get_value_present_or_fail(digestCln, "algorithm");
241 var charstring realm := f_sip_param_get_value_present_or_fail(digestCln, "realm");
242 var charstring nonce := f_sip_param_get_value_present_or_fail(digestCln, "nonce");
243
244 var template (present) CommaParam_List digestResponse := superset(
245 tr_Param("username", f_sip_str_quote(username)),
246 tr_Param("realm", f_sip_str_quote(realm)),
247 tr_Param("nonce", f_sip_str_quote(nonce)),
248 tr_Param("uri", f_sip_str_quote(uri)),
249 tr_Param("response", ?),
250 tr_Param("algorithm", algorithm),
251 tr_Param("qop", "auth"),
252 tr_Param("cnonce", ?),
253 tr_Param("nc", ?)
254 );
255 cred := tr_Credentials_DigestResponse(digestResponse);
256 authorization := tr_Authorization(cred);
257 return authorization;
258}
259
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200260private function f_ims_validate_register_contact(Contact rx_contact)
261{
262/* IMS contact shows up like this:
263 * Contact: <sip:8adf9f3d-9342-4060-aa4f-a909f37fd6f6@192.168.101.2:5060>;+g.3gpp.accesstype="cellular2";video;audio;+g.3gpp.smsip;+g.3gpp.nw-init-ussi;+g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel";+sip.instance="<urn:gsma:imei:35589811-338445-0>"
264 */
265 /* TODO: "that the UE must include the IMS Communication Service Identifier (ICSI)
266in the contact: header to indicate IMS Multimedia Telephony." */
267 /* TODO: "The UE must include an IMEI URN in the +sip.instance header field
268parameter of the contact: header." */
269 /* TODO: "If the UE supports SMS over IP, it must include the feature tag
270“+g.3gpp.smsip” in the contact: header." */
271 /* TODO: "If the UE supports conversational audio and video service, then this must
272be indicated by adding a “video” media feature tag to the contact: header." */
273}
274
275private function f_ims_parse_security_client(Security_client security_client) runs on IMS_ConnHdlr
276{
277 var boolean found := false;
278 for (var integer i := 0; i < lengthof(security_client.sec_mechanism_list); i := i + 1) {
279 var Security_mechanism sec_mec := security_client.sec_mechanism_list[i];
280 if (sec_mec.mechanism_name != "ipsec-3gpp") {
281 log("Skipping Security Mechansim: ", sec_mec.mechanism_name);
282 continue;
283 }
284 var SemicolonParam_List sec_pars := sec_mec.mechanism_params;
285 var charstring par_val;
286 par_val := f_sip_param_get_value_present_or_fail(sec_pars, "alg");
287 if (par_val != "hmac-sha-1-96") {
288 log("Skipping Security Mechansim Algo: ", par_val);
289 continue;
290 }
291 par_val := f_sip_param_get_value_present_or_fail(sec_pars, "spi-c");
292 g_pars.ipsec_remote_spi_c := str2int(par_val);
293 par_val := f_sip_param_get_value_present_or_fail(sec_pars, "spi-s");
294 g_pars.ipsec_remote_spi_s := str2int(par_val);
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200295 par_val := f_sip_param_get_value_present_or_fail(sec_pars, "port-c");
296 g_pars.ipsec_remote_port_c := str2int(par_val);
297 par_val := f_sip_param_get_value_present_or_fail(sec_pars, "port-s");
298 g_pars.ipsec_remote_port_s := str2int(par_val);
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200299 found := true;
300 break;
301 }
302
303 if (not found) {
304 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
305 log2str(g_name & "alg=hmac-sha-1-96 not found: ", security_client));
306 }
307
308 log("ipsec: remote_spi_c=", g_pars.ipsec_remote_spi_c, " remote_spi_s=", g_pars.ipsec_remote_spi_s,
309 "local_spi_c=", g_pars.ipsec_local_spi_c, " local_spi_s=", g_pars.ipsec_local_spi_s);
310}
311
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200312private function f_IMS_exec_sync(charstring cmdline, template (present) integer rc := 0)
313 runs on IMS_ConnHdlr return ASP_PResult {
314 var ASP_PResult res;
315
316 map(self:PIPE, system:PIPE);
317 res := f_PIPEasp_exec_sync_PResult(PIPE, cmdline, tr_PResult(?, ?, rc));
318 unmap(self:PIPE, system:PIPE);
319
320 return res;
321}
322
323private function f_ims_setup_ipsec() runs on IMS_ConnHdlr
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200324{
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200325 var ASP_PResult res;
326
327 var charstring cmd := mp_ipsec_setup_script_path & " " &
328 g_pars.local_sip_host & " " &
329 int2str(g_pars.local_sip_port) & " " & int2str(g_pars.ipsec_local_spi_c) & " " &
330 int2str(g_pars.local_sip_port) & " " & int2str(g_pars.ipsec_local_spi_s) & " " &
331 g_pars.remote_sip_host & " " &
332 int2str(g_pars.ipsec_remote_port_c) & " " & int2str(g_pars.ipsec_remote_spi_c) & " " &
333 int2str(g_pars.ipsec_remote_port_s) & " " & int2str(g_pars.ipsec_remote_spi_s) & " " &
334 g_pars.ipsec_auth_key;
335
336 res := f_IMS_exec_sync(cmd);
337
338 /* Debug applied rules: */
339 /*
340 res := f_IMS_exec_sync("ip xfrm state");
341 log("ip-xfrm-state Result-Stdout: " & res.stdout);
342
343 res := f_IMS_exec_sync("ip xfrm policy");
344 log("ip-xfrm-policy Result-Stdout: " & res.stdout);
345 */
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200346}
347
348/* Peer is calling us, accept it: */
349altstep as_IMS_register(boolean exp_update_to_direct_rtp := true,
350 boolean fail_others := true) runs on IMS_ConnHdlr
351{
352 var template (present) PDU_SIP_Request exp_req :=
353 tr_SIP_REGISTER(g_pars.registrar_sip_req_uri,
354 ?,
355 tr_SipAddr(),
356 tr_SipAddr(),
357 tr_Via_from(?),
358 require := tr_Require(superset("sec-agree")),
359 security_client := tr_Security_client(superset(tr_Security_mechanism("ipsec-3gpp",
360 superset(tr_Param("alg","hmac-sha-1-96"))))),
361 supported := tr_Supported(superset("path", "sec-agree")));
362 var charstring sip_expect_str := log2str(exp_req);
363
364 [] SIP.receive(exp_req) -> value g_rx_sip_req {
365 var template (value) PDU_SIP_Response tx_resp;
366 var Via via;
367 var CallidString sip_call_id;
368 var Contact contact;
369 var template (value) SipAddr from_addr;
370 var template (value) SipAddr to_addr;
371 var template (value) CommaParam_List digestCln ;
372 var template (value) WwwAuthenticate wwwAuthenticate;
373 var template (value) Security_server security_server;
374 var template (value) Server server_name := ts_Server({c_sip_server_name});
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200375 var template (value) Require require := ts_Require({"sec-agree"});
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200376 var template (value) Supported supported := ts_Supported({"sec-agree"});
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200377 var template (present) Authorization authorization;
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200378 var integer sip_seq_nr;
379 var charstring tx_sdp;
380
381 sip_call_id := g_rx_sip_req.msgHeader.callId.callid;
382 via := g_rx_sip_req.msgHeader.via;
383 via.viaBody[0].viaParams := f_sip_param_set(via.viaBody[0].viaParams, "rport", "1234"); /* TODO: set remote src port of the REGISTER */
384 from_addr := ts_SipAddr_from_Addr_Union(g_rx_sip_req.msgHeader.fromField.addressField,
385 g_rx_sip_req.msgHeader.fromField.fromParams);
386 to_addr := ts_SipAddr_from_Addr_Union(g_rx_sip_req.msgHeader.toField.addressField,
387 g_rx_sip_req.msgHeader.toField.toParams);
388 sip_seq_nr := g_rx_sip_req.msgHeader.cSeq.seqNumber;
389
390 contact := g_rx_sip_req.msgHeader.contact;
391 f_ims_validate_register_contact(contact);
392
393 /* TODO: Validate "Expires" is 600000 */
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200394
395 /* Tx 100 Tyring */
396 tx_resp := ts_SIP_Response_Trying(sip_call_id,
397 from_addr,
398 to_addr,
399 via,
400 sip_seq_nr,
401 "REGISTER",
402 allow := omit,
403 server := server_name,
404 userAgent := omit);
405 SIP.send(tx_resp);
406
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200407 g_pars.remote_sip_host := valueof(contact.contactBody.contactAddresses[0].addressField.nameAddr.addrSpec.hostPort.host);
408 f_ims_parse_security_client(g_rx_sip_req.msgHeader.security_client);
409 f_ims_setup_ipsec();
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200410
411 to_addr.params := f_sip_param_set(to_addr.params, "tag", f_sip_rand_tag());
412
413 digestCln := {
414 ts_Param("realm", f_sip_str_quote(g_pars.realm)),
415 ts_Param("qop", f_sip_str_quote("auth")),
416 ts_Param("algorithm", "AKAv1-MD5"),
Pau Espin Pedrol717379f2024-05-17 18:36:51 +0200417 ts_Param("nonce", f_sip_str_quote(f_nonce_from_rand_autn(g_pars.rand, g_pars.autn)))
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200418 /* "opaque not needed in IMS "*/
419 };
420 wwwAuthenticate := ts_WwwAuthenticate( { ts_Challenge_digestCln(digestCln) } )
421
422 /* Security-Server: ipsec-3gpp;q=0.1;prot=esp;mod=trans;spi-c=4096;spi-s=4097;port-c=5104;port-s=6104;alg=hmac-sha-1-96;ealg=null */
423 var template (value) SemicolonParam_List sec_params := {
424 ts_Param("q", "0.1"),
425 ts_Param("prot", "esp"),
426 ts_Param("mod", "trans"),
427 ts_Param("spi-c", int2str(g_pars.ipsec_local_spi_c)),
428 ts_Param("spi-s", int2str(g_pars.ipsec_local_spi_s)),
429 ts_Param("port-c", int2str(g_pars.local_sip_port)),
430 ts_Param("port-s", int2str(g_pars.local_sip_port)),
431 ts_Param("alg", "hmac-sha-1-96"),
432 ts_Param("ealg", "null")
433 };
434 security_server := ts_Security_server({
435 ts_Security_mechanism("ipsec-3gpp", sec_params)
436 });
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200437
438 /* Tx 401 Unauthorized */
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200439 tx_resp := ts_SIP_Response_Unauthorized(sip_call_id,
440 from_addr,
441 to_addr,
442 via,
443 wwwAuthenticate,
444 sip_seq_nr,
445 "REGISTER",
446 security_server := security_server,
447 server := server_name,
448 supported := supported,
449 userAgent := omit);
450 SIP.send(tx_resp);
451
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200452 /* Now we should receive a new REGISTER over ipsec: */
453
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200454 /* TODO: Generate expected Authoritzation based on AKAv1-MD5: */
455 /*authorization := f_sip_digest_gen_Authorization(valueof(wwwAuthenticate),
456 g_pars.user, g_pars.password,
457 "REGISTER",
458 f_sip_SipUrl_to_str(g_pars.registrar_sip_record.addr.nameAddr.addrSpec))
459 */
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200460 authorization := f_tr_Authorization_AKAv1MD5(valueof(wwwAuthenticate),
461 g_pars.user & "@" & g_pars.realm,
462 f_sip_SipUrl_to_str(g_pars.registrar_sip_record.addr.nameAddr.addrSpec));
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200463 /* TODO: match Authorization from above: */
464 exp_req :=
465 tr_SIP_REGISTER(g_pars.registrar_sip_req_uri,
466 ?,
467 tr_SipAddr(),
468 tr_SipAddr(),
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200469 tr_Via_from(?),
470 authorization := authorization);
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200471 SIP.receive(exp_req) -> value g_rx_sip_req;
472
473 sip_call_id := g_rx_sip_req.msgHeader.callId.callid;
474 via := g_rx_sip_req.msgHeader.via;
475 from_addr := ts_SipAddr_from_Addr_Union(g_rx_sip_req.msgHeader.fromField.addressField,
476 g_rx_sip_req.msgHeader.fromField.fromParams);
477 to_addr := ts_SipAddr_from_Addr_Union(g_rx_sip_req.msgHeader.toField.addressField,
478 g_rx_sip_req.msgHeader.toField.toParams);
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200479 sip_seq_nr := g_rx_sip_req.msgHeader.cSeq.seqNumber;
480
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200481 /* Tx 100 Trying */
482 tx_resp := ts_SIP_Response_Trying(sip_call_id,
483 from_addr,
484 to_addr,
485 via,
486 sip_seq_nr,
487 "REGISTER",
488 allow := omit,
489 server := server_name,
490 userAgent := omit);
491 SIP.send(tx_resp);
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200492
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200493 /* Tx 200 OK */
494 to_addr.params := f_sip_param_set(to_addr.params, "tag", f_sip_rand_tag());
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200495 tx_resp := ts_SIP_Response(sip_call_id,
496 from_addr,
497 to_addr,
498 "REGISTER", 200,
499 sip_seq_nr,
500 "OK",
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200501 via,
502 require := require,
503 server := server_name,
504 supported := supported,
505 userAgent := omit);
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200506 SIP.send(tx_resp);
507 }
508 [fail_others] as_SIP_fail_resp(sip_expect_str);
509 [fail_others] as_SIP_fail_req(sip_expect_str);
510
511}
512
Pau Espin Pedrolac8a0542024-04-19 17:30:57 +0200513}