blob: 56404dad86d9cab10e225850389f1203c9bace17 [file] [log] [blame]
Harald Welteb0d93602018-03-20 18:09:34 +01001module SIP_Templates {
2
3import from SIPmsg_Types all;
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02004import from TCCConversion_Functions all;
5import from TCCOpenSecurity_Functions all;
Pau Espin Pedrol95ad6a02024-04-18 16:52:46 +02006import from TCCDateTime_Functions all;
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02007import from Native_Functions all;
Pau Espin Pedrol6052a342024-03-28 20:20:46 +01008import from Osmocom_Types all;
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02009import from Misc_Helpers all;
Harald Welteb0d93602018-03-20 18:09:34 +010010
11/* wrapper type to encapsulate the Addr_Union + parameter list used in From, To. ... */
12type record SipAddr {
13 Addr_Union addr,
14 SemicolonParam_List params optional
15}
16
17const charstring c_SIP_VERSION := "SIP/2.0";
18
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +020019template (value) GenericParam ts_Param(template (value) charstring id,
20 template (omit) charstring paramValue := omit) := {
21 id := id,
22 paramValue := paramValue
23}
24template (present) GenericParam tr_Param(template (present) charstring id := ?,
25 template charstring paramValue := *) := {
26 id := id,
27 paramValue := paramValue
28}
29function f_ts_Param_omit(template (value) charstring id,
30 template (omit) charstring paramValue := omit)
31 return template (omit) GenericParam
32{
33 if (istemplatekind(paramValue, "omit")) {
34 return omit;
35 }
36 return ts_Param(id, paramValue);
37}
38
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010039template (value) SipUrl ts_SipUrl(template (value) HostPort host_port,
40 template (omit) UserInfo user_info := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +010041 scheme := "sip",
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010042 userInfo := user_info,
43 hostPort := host_port,
Harald Welteb0d93602018-03-20 18:09:34 +010044 urlParameters := omit,
45 headers := omit
46}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010047template (present) SipUrl tr_SipUrl(template (present) HostPort host_port := ?,
48 template UserInfo user_info := *) := {
Harald Welteb0d93602018-03-20 18:09:34 +010049 scheme := "sip",
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010050 userInfo := user_info,
51 hostPort := host_port,
Harald Welteb0d93602018-03-20 18:09:34 +010052 urlParameters := *,
53 headers := *
54}
55
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +020056template (value) SipUrl ts_SipUrlHost(template (value) charstring host,
57 template (omit) integer portField := omit)
58 := ts_SipUrl(ts_HostPort(host, portField));
59
60function ts_SipUrl_from_Addr_Union(template (value) Addr_Union au)
61return template (value) SipUrl {
62 if (ischosen(au.nameAddr)) {
63 return au.nameAddr.addrSpec;
64 } else { /* au.addrSpecUnion */
65 return au.addrSpecUnion;
66 }
67}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +010068
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +020069// [20.5]
70template (present) Allow tr_Allow(template Method_List methods := *) := {
71 fieldName := ALLOW_E,
72 methods := methods
73}
74template (value) Allow ts_Allow(template (omit) Method_List methods := omit) := {
75 fieldName := ALLOW_E,
76 methods := methods
77}
78
Pau Espin Pedrola674d612024-05-14 19:56:33 +020079template (present) Credentials tr_Credentials_DigestResponse(template (present) CommaParam_List digestResponse) := {
80 digestResponse := digestResponse
81}
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +020082template (value) Credentials ts_Credentials_DigestResponse(template (value) CommaParam_List digestResponse) := {
83 digestResponse := digestResponse
84}
85
86template (value) Credentials ts_Credentials_DigestResponseMD5(
87 template (value) charstring username,
88 template (value) charstring realm,
89 template (value) charstring nonce,
90 template (value) charstring uri,
91 template (value) charstring response,
92 template (value) charstring opaque,
93 template (value) charstring algorithm := "MD5",
94 template (value) charstring qop := "auth",
95 template (omit) charstring cnonce := omit,
96 template (omit) charstring nc := omit
97 ) := {
98 digestResponse := {
99 // Already added by digestResponse automatically:
100 //ts_Param("Digest", omit),
101 ts_Param("username", f_sip_str_quote(username)),
102 ts_Param("realm", f_sip_str_quote(realm)),
103 ts_Param("nonce", f_sip_str_quote(nonce)),
104 ts_Param("uri", f_sip_str_quote(uri)),
105 ts_Param("response", f_sip_str_quote(response)),
106 ts_Param("opaque", f_sip_str_quote(opaque)),
107 ts_Param("algorithm", algorithm),
108 ts_Param("qop", qop),
109 // FIXME: If "omit" is passed, these below end up in;
110 // "Dynamic test case error: Performing a valueof or send operation on a non-specific template of type @SIPmsg_Types.GenericParam"
111 f_ts_Param_omit("cnonce", f_sip_str_quote(cnonce)),
112 f_ts_Param_omit("nc", nc)
113 }
114}
115
116template (value) Credentials ts_Credentials_OtherAuth(template (value) OtherAuth otherResponse) := {
117 otherResponse := otherResponse
118}
119
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200120template (present) Authorization tr_Authorization(template (present) Credentials body) := {
121 fieldName := AUTHORIZATION_E,
122 body := body
123}
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200124template (value) Authorization ts_Authorization(template (value) Credentials body) := {
125 fieldName := AUTHORIZATION_E,
126 body := body
127}
128
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100129// [20.10]
130template (present) NameAddr tr_NameAddr(template (present) SipUrl addrSpec := ?,
131 template charstring displayName := *) := {
132 displayName := displayName,
133 addrSpec := addrSpec
Harald Welteb0d93602018-03-20 18:09:34 +0100134}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100135template (value) NameAddr ts_NameAddr(template (value) SipUrl addrSpec,
136 template (omit) charstring displayName := omit) := {
137 displayName := displayName,
138 addrSpec := addrSpec
139}
140
141template (present) Addr_Union tr_Addr_Union_NameAddr(template (present) NameAddr nameAddr := ?) := {
142 nameAddr := nameAddr
143}
144template (value) Addr_Union ts_Addr_Union_NameAddr(template (value) NameAddr nameAddr) := {
145 nameAddr := nameAddr
146}
147
148template (present) Addr_Union tr_Addr_Union_SipUrl(template (present) SipUrl sipUrl := ?) := {
149 addrSpecUnion := sipUrl
150}
151template (value) Addr_Union ts_Addr_Union_SipUrl(template (value) SipUrl sipUrl) := {
152 addrSpecUnion := sipUrl
153}
154
155
156template (present) ContactAddress tr_ContactAddress(template (present) Addr_Union addressField := ?,
157 template SemicolonParam_List contactParams := *) := {
158 addressField := addressField,
159 contactParams := contactParams
160}
161template (value) ContactAddress ts_ContactAddress(template (value) Addr_Union addressField,
162 template (omit) SemicolonParam_List contactParams := omit) := {
163 addressField := addressField,
164 contactParams := contactParams
165}
166
167template (present) Contact tr_Contact(template (present) ContactAddress_List contactAddresses := ?) := {
168 fieldName := CONTACT_E,
169 contactBody := {
170 contactAddresses := contactAddresses
171 }
172}
173template (value) Contact ts_Contact(template (value) ContactAddress_List contactAddresses) := {
174 fieldName := CONTACT_E,
175 contactBody := {
176 contactAddresses := contactAddresses
177 }
178}
179
180template (value) Contact ts_ContactWildcard := {
181 fieldName := CONTACT_E,
182 contactBody := {
183 wildcard := "*"
184 }
185}
186
187template (present) Contact tr_Contact_SipAddr(template (present) SipAddr contact_addr := ?)
188 := tr_Contact({ tr_ContactAddress(contact_addr.addr, contact_addr.params) });
189
190private function f_tr_Contact_SipAddr(template SipAddr contact_addr) return template Contact
191{
192 if (istemplatekind(contact_addr, "omit")) {
193 return omit;
194 } else if (istemplatekind(contact_addr, "*")) {
195 return *;
196 }
197 return tr_Contact_SipAddr(contact_addr);
198}
199
200template (value) Contact ts_Contact_SipAddr(template (value) SipAddr contact_addr)
201 := ts_Contact({ ts_ContactAddress(contact_addr.addr, contact_addr.params) });
202private function ts_Contact_SipAddr_omit(template (omit) SipAddr contact_addr := omit) return template (omit) Contact
203{
204 if (istemplatekind(contact_addr, "omit")) {
205 return omit;
206 }
207 return ts_Contact_SipAddr(contact_addr);
208}
209
210
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200211// [20.14]
212template (value) ContentLength ts_ContentLength(template (value) integer len := 0) := {
213 fieldName := CONTENT_LENGTH_E,
214 len := len
215}
216template (present) ContentLength tr_ContentLength(template (present) integer len := ?) := {
217 fieldName := CONTENT_LENGTH_E,
218 len := len
219}
220
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100221// [20.19]
222template (value) Expires ts_Expires(template (value) DeltaSec deltaSec := "7200") := {
223 fieldName := EXPIRES_E,
224 deltaSec := deltaSec
225}
226
Pau Espin Pedrol0c5c6472024-05-21 13:13:49 +0200227// [RFC3455 5.4] + 3GPP 24.229 V8.7.0
228template (present) Access_net_spec tr_Access_net_spec(template (present) charstring access_type := ?,
229 template SemicolonParam_List access_info := *) := {
230 access_type := access_type,
231 access_info := access_info
232}
233template (present) Access_net_spec tr_Access_net_spec_EUTRAN(template (present) charstring uli_str := ?) := {
234 access_type := "3GPP-E-UTRAN-FDD",
235 access_info := {tr_Param("utran-cell-id-3gpp", uli_str)}
236}
237
238// [RFC3455 5.4] + 3GPP 24.229 V8.7.0
239template (present) P_Access_Network_Info tr_P_Access_Network_Info(template (present) Access_net_spec_list access_net_specs := ?) := {
240 fieldName := P_ACCESS_NETWORK_INFO,
241 access_net_specs := access_net_specs
242}
243
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200244
245// [20.32]
246template (value) Require ts_Require(template (value) OptionTag_List optionsTags := {}) := {
247 fieldName := REQUIRE_E,
248 optionsTags := optionsTags
249}
250template (present) Require tr_Require(template (present) OptionTag_List optionsTags := ?) := {
251 fieldName := REQUIRE_E,
252 optionsTags := optionsTags
253}
254
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200255// [20.35 RFC2616 14.38]
256template (value) Server ts_Server(template (value) ServerVal_List serverBody := {}) := {
257 fieldName := SERVER_E,
258 serverBody := serverBody
259}
260template (present) Server tr_Server(template (present) ServerVal_List serverBody := ?) := {
261 fieldName := SERVER_E,
262 serverBody := serverBody
263}
264
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200265// [20.37]
266template (value) Supported ts_Supported(template (value) OptionTag_List optionsTags := {}) := {
267 fieldName := SUPPORTED_E,
268 optionsTags := optionsTags
269}
270template (present) Supported tr_Supported(template (present) OptionTag_List optionsTags := ?) := {
271 fieldName := SUPPORTED_E,
272 optionsTags := optionsTags
273}
274
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200275// [20.41 RFC2616 14.43]
276template (value) UserAgent ts_UserAgent(template (value) ServerVal_List userAgentBody := {}) := {
277 fieldName := USER_AGENT_E,
278 userAgentBody := userAgentBody
279}
280template (present) UserAgent tr_UserAgent(template (present) ServerVal_List userAgentBody := ?) := {
281 fieldName := USER_AGENT_E,
282 userAgentBody := userAgentBody
283}
284
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200285
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100286template (value) SipAddr ts_SipAddr(template (value) HostPort host_port,
287 template (omit) UserInfo user_info := omit,
288 template (omit) charstring displayName := omit,
289 template (omit) SemicolonParam_List params := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100290 addr := {
291 nameAddr := {
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100292 displayName := displayName,
293 addrSpec := ts_SipUrl(host_port, user_info)
Harald Welteb0d93602018-03-20 18:09:34 +0100294 }
295 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100296 params := params
297}
298template (present) SipAddr tr_SipAddr(template (present) HostPort host_port := ?,
299 template UserInfo user_info := *,
300 template charstring displayName := *,
301 template SemicolonParam_List params := *) := {
302 addr := {
303 nameAddr := {
304 displayName := displayName,
305 addrSpec := tr_SipUrl(host_port, user_info)
306 }
307 },
308 params := params
Harald Welteb0d93602018-03-20 18:09:34 +0100309}
310
311/* build a receive template from a value: substitute '*' for omit */
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200312function tr_SipUrl_from_val(template (value) SipUrl tin) return template (present) SipUrl {
313 var template (present) SipUrl ret := tin;
314
315 /* if the port number is 5060, it may be omitted */
316 if (ispresent(tin.hostPort.portField) and
317 valueof(tin.hostPort.portField) == 5060) {
318 ret.hostPort.portField := 5060 ifpresent;
319 }
320 if (not ispresent(tin.userInfo.password)) {
321 ret.userInfo.password := *;
322 }
323
324 return ret;
325}
326function tr_SipAddr_from_val(template (value) SipAddr tin) return template (present) SipAddr {
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100327 var template (present) SipAddr ret := tin;
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200328
329 if (not ispresent(tin.addr.nameAddr.displayName)) {
Harald Welteb0d93602018-03-20 18:09:34 +0100330 ret.addr.nameAddr.displayName := *;
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200331 } else if (f_str_tolower(f_sip_str_unquote(tin.addr.nameAddr.displayName)) == "anonymous") {
332 /* if the user is Anonymous, it may be omitted */
333 ret.addr.nameAddr.displayName := tin.addr.nameAddr.displayName ifpresent;
Harald Welteb0d93602018-03-20 18:09:34 +0100334 }
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200335
336 ret.addr.nameAddr.addrSpec := tr_SipUrl_from_val(tin.addr.nameAddr.addrSpec);
337
338 if (not ispresent(tin.params)) {
Harald Welteb0d93602018-03-20 18:09:34 +0100339 ret.params := *;
340 }
341 return ret;
342}
343
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200344function ts_SipAddr_from_Addr_Union(template (value) Addr_Union au,
345 template (omit) SemicolonParam_List params := omit)
346return template (value) SipAddr {
347 var template (value) SipUrl addrSpec := ts_SipUrl_from_Addr_Union(au);
348 var template (omit) charstring displayName;
349
350 if (ischosen(au.nameAddr)) {
351 displayName := au.nameAddr.displayName;
352 } else { /* au.addrSpecUnion */
353 displayName := omit
354 }
355
356 return ts_SipAddr(addrSpec.hostPort,
357 addrSpec.userInfo,
358 displayName,
359 params);
360}
361
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100362template (value) HostPort ts_HostPort(template (omit) charstring host := omit,
363 template (omit) integer portField := omit) := {
364 host := host,
365 portField := portField
366}
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200367
368template (present) HostPort tr_HostPort(template charstring host := *,
369 template integer portField := *) := {
370 host := host,
371 portField := portField
372}
373function f_tr_HostPort(template charstring host := *,
374 template integer portField := *)
375return template (present) HostPort {
376 return f_tr_HostPort_opt_defport(tr_HostPort(host, portField));
377}
378function f_tr_HostPort_opt_defport(template (present) HostPort hp) return template (present) HostPort {
379 var template (present) HostPort hpout := hp;
Harald Welteb0d93602018-03-20 18:09:34 +0100380 /* if the port number is 5060, it may be omitted */
381 if (isvalue(hp.portField) and valueof(hp.portField) == 5060) {
382 hpout.portField := 5060 ifpresent;
383 }
384 return hpout;
385}
386
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200387function f_tr_SipUrl_opt_defport(template (present) SipUrl url) return template (present) SipUrl {
388 var template (present) SipUrl urlout := url;
389 urlout.hostPort := f_tr_HostPort_opt_defport(url.hostPort);
390 return urlout;
391}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100392
393template (value) UserInfo ts_UserInfo(template (value) charstring userOrTelephoneSubscriber,
394 template (omit) charstring password := omit) := {
395 userOrTelephoneSubscriber := userOrTelephoneSubscriber,
396 password := password
397}
398template (present) UserInfo tr_UserInfo(template (present) charstring userOrTelephoneSubscriber := ?,
399 template charstring password := *) := {
400 userOrTelephoneSubscriber := userOrTelephoneSubscriber,
401 password := password
402}
403
404template (value) RequestLine ts_SIP_ReqLine(Method method,
405 template (value) SipUrl uri,
Harald Welteb0d93602018-03-20 18:09:34 +0100406 charstring ver := c_SIP_VERSION) := {
407 method := method,
408 requestUri := uri,
409 sipVersion := ver
410}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100411template (present) RequestLine tr_SIP_ReqLine(template (present) Method method := ?,
412 template (present) SipUrl uri := ?,
413 template (present) charstring ver := c_SIP_VERSION) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100414 method := method,
415 requestUri := uri,
416 sipVersion := ver
417}
418
419template (value) StatusLine ts_SIP_StatusLine(integer status_code, charstring reason) := {
420 sipVersion := "SIP/2.0",
421 statusCode := status_code,
422 reasonPhrase := reason
423}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100424template (present) StatusLine tr_SIP_StatusLine(template integer status_code,
425 template charstring reason) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100426 sipVersion := "SIP/2.0",
427 statusCode := status_code,
428 reasonPhrase := reason
429}
430
431
432template (value) PDU_SIP_Request ts_SIP_req(template (value) RequestLine rl) := {
433 requestLine := rl,
434 msgHeader := c_SIP_msgHeader_empty,
435 messageBody := omit,
436 payload := omit
437}
438
439const Method_List c_SIP_defaultMethods := {
440 "INVITE", "ACK", "BYE", "CANCEL", "OPTIONS", "PRACK", "MESSAGE", "SUBSCRIBE",
441 "NOTIFY", "REFER", "UPDATE" };
442
443private function f_ContentTypeOrOmit(template (omit) ContentType ct, template (omit) charstring body)
444return template (omit) ContentType {
445 /* if user explicitly stated no content type */
446 if (istemplatekind(ct, "omit")) {
447 return omit;
448 }
449 /* if there's no body, then there's no content-type either */
450 if (istemplatekind(body, "omit")) {
451 return omit;
452 }
453 return ct;
454}
455
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200456private function f_ContentLength(template (omit) charstring body)
457return template (value) ContentLength {
458 /* rfc3261 20.14: "If no body is present in a message, then the
459 * Content-Length header field value MUST be set to zero." */
460 if (istemplatekind(body, "omit")) {
461 return ts_ContentLength(0);
462 }
463 return ts_ContentLength(lengthof(body));
464}
465
Harald Welteb0d93602018-03-20 18:09:34 +0100466template (value) ContentType ts_CT_SDP := {
467 fieldName := CONTENT_TYPE_E,
468 mediaType := "application/sdp"
469};
470
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200471template (value) Via ts_Via_from(template (value) HostPort addr,
472 template (value) charstring transport := "UDP") := {
Harald Welteb0d93602018-03-20 18:09:34 +0100473 fieldName := VIA_E,
474 viaBody := {
475 {
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200476 sentProtocol := { "SIP", "2.0", transport },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100477 sentBy := addr,
Harald Welteb0d93602018-03-20 18:09:34 +0100478 viaParams := omit
479 }
480 }
481}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100482template (present) Via tr_Via_from(template (present) HostPort host_port := ?,
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200483 template (present) charstring transport := ?,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100484 template SemicolonParam_List viaParams := *) := {
485 fieldName := VIA_E,
486 viaBody := {
487 {
Pau Espin Pedrol2a833372024-05-10 20:23:22 +0200488 sentProtocol := { "SIP", "2.0", ? },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100489 sentBy := host_port,
490 viaParams := viaParams
491 }
492 }
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200493}
494
495template (present) OtherAuth
496tr_OtherAuth(template (present) charstring authScheme := ?,
497 template (present) CommaParam_List authParams := ?) := {
498 authScheme := authScheme,
499 authParams := authParams
500}
501
502template (value) OtherAuth
503ts_OtherAuth(template (value) charstring authScheme,
504 template (value) CommaParam_List authParams) := {
505 authScheme := authScheme,
506 authParams := authParams
507}
508
509template (present) Challenge
510tr_Challenge_digestCln(template (present) CommaParam_List digestCln := ?) := {
511 digestCln := digestCln
512}
513
514template (value) Challenge
515ts_Challenge_digestCln(template (value) CommaParam_List digestCln) := {
516 digestCln := digestCln
517}
518
519template (present) Challenge
520tr_Challenge_otherChallenge(template (present) OtherAuth otherChallenge := ?) := {
521 otherChallenge := otherChallenge
522}
523
524template (value) Challenge
525ts_Challenge_otherChallenge(template (value) OtherAuth otherChallenge) := {
526 otherChallenge := otherChallenge
527}
528
529template (present) WwwAuthenticate
530tr_WwwAuthenticate(template (present) Challenge_list challenge := ?) := {
531 fieldName := WWW_AUTHENTICATE_E,
532 challenge := challenge
533}
534
535template (value) WwwAuthenticate
536ts_WwwAuthenticate(template (value) Challenge_list challenge) := {
537 fieldName := WWW_AUTHENTICATE_E,
538 challenge := challenge
539}
Harald Welteb0d93602018-03-20 18:09:34 +0100540
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200541// RFC3329
542template (present) Security_client
543tr_Security_client(template (present) Security_mechanism_list sec_mechanism_list := ?) := {
544 fieldName := SECURITY_CLIENT_E,
545 sec_mechanism_list := sec_mechanism_list
546}
547template (value) Security_client
548ts_Security_client(template (value) Security_mechanism_list sec_mechanism_list) := {
549 fieldName := SECURITY_CLIENT_E,
550 sec_mechanism_list := sec_mechanism_list
551}
552
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200553template (present) Security_server
554tr_Security_server(template (present) Security_mechanism_list sec_mechanism_list := ?) := {
555 fieldName := SECURITY_SERVER_E,
556 sec_mechanism_list := sec_mechanism_list
557}
558template (value) Security_server
559ts_Security_server(template (value) Security_mechanism_list sec_mechanism_list) := {
560 fieldName := SECURITY_SERVER_E,
561 sec_mechanism_list := sec_mechanism_list
562}
563
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200564template (present) Security_mechanism
565tr_Security_mechanism(template (present) charstring name := ?,
566 template SemicolonParam_List params := *) := {
567 mechanism_name := name,
568 mechanism_params := params
569}
570template (value) Security_mechanism
571ts_Security_mechanism(template (value) charstring name,
572 template (omit) SemicolonParam_List params := omit) := {
573 mechanism_name := name,
574 mechanism_params := params
575}
576
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100577template (value) MessageHeader ts_SIP_msgHeader_empty := c_SIP_msgHeader_empty;
578template (value) MessageHeader
579ts_SIP_msgh_std(template (value) CallidString call_id,
580 template (value) SipAddr from_addr,
581 template (value) SipAddr to_addr,
582 template (omit) Contact contact,
583 template (value) charstring method,
584 template (value) integer seq_nr,
585 template (value) Via via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200586 template (omit) ContentLength content_length := ts_ContentLength(0),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100587 template (omit) ContentType content_type := omit,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200588 template (omit)Authorization authorization := omit,
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200589 template (omit) Allow allow := ts_Allow(c_SIP_defaultMethods),
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200590 template (omit) Expires expires := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200591 template (omit) Require require := omit,
592 template (omit) Security_client security_client := omit,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200593 template (omit) Security_server security_server := omit,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200594 template (omit) Server server := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200595 template (omit) Supported supported := omit,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200596 template (omit) UserAgent userAgent := ts_UserAgent({ "osmo-ttcn3-hacks/0.23" }),
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200597 template (omit) WwwAuthenticate wwwAuthenticate := omit
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100598 ) modifies ts_SIP_msgHeader_empty := {
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200599 allow := allow,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200600 authorization := authorization,
Harald Welteb0d93602018-03-20 18:09:34 +0100601 callId := {
602 fieldName := CALL_ID_E,
603 callid := call_id
604 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100605 contact := contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200606 contentLength := content_length,
Harald Welteb0d93602018-03-20 18:09:34 +0100607 contentType := content_type,
608 cSeq := {
609 fieldName := CSEQ_E,
610 seqNumber := seq_nr,
611 method := method
612 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100613 expires := expires,
Harald Welteb0d93602018-03-20 18:09:34 +0100614 fromField := {
615 fieldName := FROM_E,
616 addressField := from_addr.addr,
617 fromParams := from_addr.params
618 },
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200619 require := require,
620 security_client := security_client,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200621 security_server := security_server,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200622 server := server,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200623 supported := supported,
Harald Welteb0d93602018-03-20 18:09:34 +0100624 toField := {
625 fieldName := TO_E,
626 addressField := to_addr.addr,
627 toParams := to_addr.params
628 },
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200629 userAgent := userAgent,
Pau Espin Pedrol89d8c952024-05-10 20:28:24 +0200630 via := via,
631 wwwAuthenticate := wwwAuthenticate
Harald Welteb0d93602018-03-20 18:09:34 +0100632}
633
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100634template (present) MessageHeader
635tr_SIP_msgh_std(template CallidString call_id,
636 template SipAddr from_addr,
637 template SipAddr to_addr,
638 template Contact contact,
639 template (present) Via via := tr_Via_from(?),
640 template charstring method,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100641 template integer seq_nr := ?,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200642 template ContentLength content_length := *,
643 template ContentType content_type := *,
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200644 template Allow allow := *,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200645 template Authorization authorization := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200646 template Expires expires := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200647 template Require require := *,
648 template Security_client security_client := *,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200649 template Security_server security_server := *,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200650 template Server server := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200651 template Supported supported := *,
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200652 template UserAgent userAgent := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200653 template WwwAuthenticate wwwAuthenticate := *
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100654 ) modifies t_SIP_msgHeader_any := {
Pau Espin Pedrolcb3a15b2024-05-13 16:25:11 +0200655 allow := allow,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200656 authorization := authorization,
Harald Welteb0d93602018-03-20 18:09:34 +0100657 callId := {
658 fieldName := CALL_ID_E,
659 callid := call_id
660 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100661 contact := contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200662 contentLength := content_length,
Harald Welteb0d93602018-03-20 18:09:34 +0100663 contentType := content_type,
664 cSeq := {
665 fieldName := CSEQ_E,
666 seqNumber := seq_nr,
667 method := method
668 },
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100669 expires := expires,
Harald Welteb0d93602018-03-20 18:09:34 +0100670 fromField := {
671 fieldName := FROM_E,
672 addressField := from_addr.addr,
673 fromParams := from_addr.params
674 },
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200675 require := require,
676 security_client := security_client,
Pau Espin Pedrol7f411562024-05-13 13:58:41 +0200677 security_server := security_server,
Pau Espin Pedrol52cc2e52024-05-13 17:50:20 +0200678 server := server,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200679 supported := supported,
Harald Welteb0d93602018-03-20 18:09:34 +0100680 toField := {
681 fieldName := TO_E,
682 addressField := to_addr.addr,
683 toParams := to_addr.params
684 },
Pau Espin Pedrol13c50ac2024-05-13 17:48:09 +0200685 userAgent := userAgent,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200686 via := via,
687 wwwAuthenticate := wwwAuthenticate
Harald Welteb0d93602018-03-20 18:09:34 +0100688}
689
690
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100691template (value) PDU_SIP_Request
692ts_SIP_REGISTER(template (value) SipUrl sip_url_host_port,
693 template (value) CallidString call_id,
694 template (value) SipAddr from_addr,
695 template (value) SipAddr to_addr,
696 template (value) Via via,
697 integer seq_nr,
698 template (omit) Contact contact,
699 template (omit) Expires expires,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200700 template (omit) Authorization authorization := omit,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200701 template (omit) Require require := omit,
702 template (omit) Security_client security_client := omit,
703 template (omit) Supported supported := omit,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100704 template (omit) charstring body := omit) := {
705 requestLine := ts_SIP_ReqLine(REGISTER_E, sip_url_host_port),
706 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
707 "REGISTER", seq_nr, via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200708 content_length := f_ContentLength(body),
709 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200710 authorization := authorization,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200711 expires := expires,
712 require := require,
713 security_client := security_client,
714 supported := supported),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100715 messageBody := body,
716 payload := omit
717}
718template (present) PDU_SIP_Request
719tr_SIP_REGISTER(template (present) SipUrl sip_url_host_port := ?,
720 template (present) CallidString call_id := ?,
721 template (present) SipAddr from_addr := ?,
722 template (present) SipAddr to_addr := ?,
Pau Espin Pedrol0dd3f262024-04-25 17:04:43 +0200723 template (present) Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100724 template integer seq_nr := *,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200725 template Authorization authorization := *,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100726 template Contact contact := *,
727 template Expires expires := *,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200728 template Require require := *,
729 template Security_client security_client := *,
730 template Supported supported := *,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100731 template charstring body := *) := {
732 requestLine := tr_SIP_ReqLine(REGISTER_E, sip_url_host_port),
733 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200734 via, "REGISTER", seq_nr,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200735 authorization := authorization,
Pau Espin Pedrol73f6a312024-05-10 20:30:16 +0200736 expires := expires,
737 require := require,
738 security_client := security_client,
739 supported := supported),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100740 messageBody := body,
741 payload := omit
742}
743
744template (value) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200745ts_SIP_INVITE(template (value) CallidString call_id,
746 template (value) SipAddr from_addr,
747 template (value) SipAddr to_addr,
748 template (value) Via via,
749 template (value) Contact contact,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100750 integer seq_nr,
751 template (omit) charstring body := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100752 requestLine := ts_SIP_ReqLine(INVITE_E, to_addr.addr.nameAddr.addrSpec),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200753 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100754 "INVITE", seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200755 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200756 content_length := f_ContentLength(body),
757 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100758 messageBody := body,
759 payload := omit
760}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100761template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200762tr_SIP_INVITE(template (present) SipUrl uri,
763 template CallidString call_id,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100764 template SipAddr from_addr,
765 template SipAddr to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200766 template Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100767 template integer seq_nr,
768 template charstring body) := {
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200769 requestLine := tr_SIP_ReqLine(INVITE_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100770 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, ?,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200771 via, "INVITE", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100772 messageBody := body,
773 payload := omit
774}
775
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100776template (value) PDU_SIP_Request
777ts_SIP_BYE(CallidString call_id,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200778 template (value) SipAddr from_addr,
779 template (value) SipAddr to_addr,
780 template (value) Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100781 integer seq_nr,
782 template (omit) charstring body) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100783 requestLine := ts_SIP_ReqLine(BYE_E, to_addr.addr.nameAddr.addrSpec),
784 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, "BYE", seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200785 via,
786 content_length := f_ContentLength(body),
787 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100788 messageBody := body,
789 payload := omit
790}
791
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100792template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200793tr_SIP_BYE(template (present) SipUrl uri,
794 template CallidString call_id,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100795 template SipAddr from_addr,
796 template SipAddr to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200797 template Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100798 template integer seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200799 template charstring body := *) := {
800 requestLine := tr_SIP_ReqLine(BYE_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100801 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200802 via, "BYE", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100803 messageBody := body,
804 payload := omit
805}
806
807
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100808template (value) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200809ts_SIP_ACK(template (value) CallidString call_id,
810 template (value) SipAddr from_addr,
811 template (value) SipAddr to_addr,
812 template (value) Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100813 integer seq_nr,
814 template (omit) charstring body) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100815 requestLine := ts_SIP_ReqLine(ACK_E, to_addr.addr.nameAddr.addrSpec),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100816 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr,
817 ts_Contact_SipAddr(from_addr),
818 "ACK", seq_nr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200819 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200820 content_length := f_ContentLength(body),
821 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Harald Welteb0d93602018-03-20 18:09:34 +0100822 messageBody := body,
823 payload := omit
824}
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100825template (present) PDU_SIP_Request
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200826tr_SIP_ACK(template (present) SipUrl uri,
827 template CallidString call_id,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100828 template SipAddr from_addr,
829 template SipAddr to_addr,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200830 template Via via,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100831 template integer seq_nr,
832 template charstring body) := {
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200833 requestLine := tr_SIP_ReqLine(ACK_E, uri),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100834 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200835 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200836 "ACK", seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100837 messageBody := body,
838 payload := omit
839}
840
Pau Espin Pedrol32167d82024-04-10 13:14:51 +0200841template (present) PDU_SIP_Request
842tr_SIP_CANCEL(template (present) SipUrl uri,
843 template (present) CallidString call_id,
844 template (present) SipAddr from_addr,
845 template (present) SipAddr to_addr,
846 template (present) Via via,
847 template (present) integer seq_nr,
848 template charstring body := *) := {
849 requestLine := tr_SIP_ReqLine(CANCEL_E, uri),
850 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
851 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200852 "CANCEL", seq_nr),
Pau Espin Pedrol32167d82024-04-10 13:14:51 +0200853 messageBody := body,
854 payload := omit
855}
856
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100857template (value) PDU_SIP_Response
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200858ts_SIP_Response(template (value) CallidString call_id,
859 template (value) SipAddr from_addr,
860 template (value) SipAddr to_addr,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100861 charstring method,
862 integer status_code,
863 integer seq_nr,
864 charstring reason,
865 Via via,
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200866 template (omit) Allow allow := omit,
867 template (omit) Require require := omit,
868 template (omit) Server server := omit,
869 template (omit) Supported supported := omit,
870 template (omit) UserAgent userAgent := omit,
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100871 template (omit) charstring body := omit) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100872 statusLine := ts_SIP_StatusLine(status_code, reason),
873 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200874 via,
875 content_length := f_ContentLength(body),
Pau Espin Pedrola674d612024-05-14 19:56:33 +0200876 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
877 allow := allow,
878 require := require,
879 server := server,
880 supported := supported,
881 userAgent := userAgent),
Harald Welteb0d93602018-03-20 18:09:34 +0100882 messageBody := body,
883 payload := omit
884}
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +0200885/* 100 Trying */
886template (value) PDU_SIP_Response
887ts_SIP_Response_Trying(
888 template (value) CallidString call_id,
889 template (value) SipAddr from_addr,
890 template (value) SipAddr to_addr,
891 Via via,
892 integer seq_nr,
893 charstring method := "INVITE",
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200894 template (omit) Allow allow := omit,
895 template (omit) Server server := omit,
896 template (omit) UserAgent userAgent := omit,
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +0200897 template (omit) charstring body := omit) := {
898 statusLine := ts_SIP_StatusLine(100, "Trying"),
899 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200900 via,
901 content_length := f_ContentLength(body),
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200902 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
903 allow := allow,
904 server := server,
905 userAgent := userAgent),
Pau Espin Pedrol1b5f7ba2024-05-13 16:38:38 +0200906 messageBody := body,
907 payload := omit
908}
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200909/* 180 Ringing */
910template (value) PDU_SIP_Response
911ts_SIP_Response_Ringing(
912 template (value) CallidString call_id,
913 template (value) SipAddr from_addr,
914 template (value) SipAddr to_addr,
915 Via via,
916 integer seq_nr,
917 charstring method := "INVITE",
918 template (omit) charstring body := omit) := {
919 statusLine := ts_SIP_StatusLine(180, "Ringing"),
920 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200921 via,
922 content_length := f_ContentLength(body),
923 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200924 messageBody := body,
925 payload := omit
926}
927
Pau Espin Pedrola2812ec2024-05-10 20:30:44 +0200928/* 401 Unauthorized */
929template (value) PDU_SIP_Response
930ts_SIP_Response_Unauthorized(
931 template (value) CallidString call_id,
932 template (value) SipAddr from_addr,
933 template (value) SipAddr to_addr,
934 Via via,
935 template (value) WwwAuthenticate wwwAuthenticate,
936 integer seq_nr,
937 charstring method := "REGISTER",
938 template (omit) Allow allow := omit,
939 template (omit) Security_server security_server := omit,
940 template (omit) Server server := omit,
941 template (omit) Supported supported := omit,
942 template (omit) UserAgent userAgent := omit,
943 template (omit) charstring body := omit) := {
944 statusLine := ts_SIP_StatusLine(401, "Unauthorized"),
945 msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
946 via,
947 content_length := f_ContentLength(body),
948 content_type := f_ContentTypeOrOmit(ts_CT_SDP, body),
949 allow := allow,
950 security_server := security_server,
951 server := server,
952 supported := supported,
953 userAgent := userAgent,
954 wwwAuthenticate := wwwAuthenticate),
955 messageBody := body,
956 payload := omit
957}
958
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100959template (present) PDU_SIP_Response
960tr_SIP_Response(template CallidString call_id,
961 template SipAddr from_addr,
962 template SipAddr to_addr,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200963 template (present) Via via := tr_Via_from(?),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100964 template Contact contact,
965 template charstring method,
966 template integer status_code,
967 template integer seq_nr := ?,
968 template charstring reason := ?,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200969 template charstring body := *) := {
Harald Welteb0d93602018-03-20 18:09:34 +0100970 statusLine := tr_SIP_StatusLine(status_code, reason),
Pau Espin Pedrolfb34d862024-03-28 20:21:38 +0100971 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200972 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200973 method, seq_nr),
Harald Welteb0d93602018-03-20 18:09:34 +0100974 messageBody := body,
975 payload := omit
976}
977
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200978/* Expect during first REGISTER/INVITE/... when authorization is required: */
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +0100979template (present) PDU_SIP_Response
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +0200980tr_SIP_Response_Unauthorized(
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +0100981 template CallidString call_id,
982 template SipAddr from_addr,
983 template SipAddr to_addr,
984 template (present) Via via := tr_Via_from(?),
985 template Contact contact := *,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200986 template (present) WwwAuthenticate wwwAuthenticate := ?,
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +0100987 template integer seq_nr := ?,
988 template charstring method := "REGISTER",
989 template integer status_code := 401,
990 template charstring reason := "Unauthorized",
991 template charstring body := *) := {
992 statusLine := tr_SIP_StatusLine(status_code, reason),
993 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
994 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +0200995 method, seq_nr,
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +0200996 wwwAuthenticate := wwwAuthenticate),
Pau Espin Pedrol37ee0ed2024-03-28 21:17:12 +0100997 messageBody := body,
998 payload := omit
999}
Harald Welteb0d93602018-03-20 18:09:34 +01001000
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001001/* 100 Trying */
1002template (present) PDU_SIP_Response
1003tr_SIP_Response_Trying(
1004 template CallidString call_id,
1005 template SipAddr from_addr,
1006 template SipAddr to_addr,
1007 template (present) Via via := tr_Via_from(?),
1008 template integer seq_nr := ?,
1009 template charstring method := "INVITE",
1010 template integer status_code := 100,
1011 template charstring reason := "Trying",
1012 template charstring body := *) := {
1013 statusLine := tr_SIP_StatusLine(status_code, reason),
1014 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
1015 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001016 method, seq_nr),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001017 messageBody := body,
1018 payload := omit
1019}
1020
1021/* 180 Ringing */
1022template (present) PDU_SIP_Response
1023tr_SIP_Response_Ringing(
1024 template CallidString call_id,
1025 template SipAddr from_addr,
1026 template SipAddr to_addr,
1027 template (present) Via via := tr_Via_from(?),
1028 template integer seq_nr := ?,
1029 template charstring method := "INVITE",
1030 template integer status_code := 180,
1031 template charstring reason := "Ringing",
1032 template charstring body := *) := {
1033 statusLine := tr_SIP_StatusLine(status_code, reason),
1034 msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
1035 via,
Pau Espin Pedrol5c36a652024-05-14 16:05:59 +02001036 method, seq_nr),
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001037 messageBody := body,
1038 payload := omit
1039}
1040
1041/****************
1042 * FUNCTIONS:
1043 ****************/
1044
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001045function f_sip_param_find(GenericParam_List li,
1046 template (present) charstring id := ?)
1047return template (omit) GenericParam {
1048 var integer i;
1049
1050 for (i := 0; i < lengthof(li); i := i + 1) {
1051 if (not ispresent(li[i])) {
1052 continue;
1053 }
1054 if (match(li[i].id, id)) {
1055 return li[i];
1056 }
1057 }
1058 return omit;
1059}
1060
1061function f_sip_param_find_or_fail(GenericParam_List li,
1062 template (present) charstring id := ?)
1063return GenericParam {
1064 var template (omit) GenericParam parameter;
1065 parameter := f_sip_param_find(li, id);
1066 if (istemplatekind(parameter, "omit")) {
1067 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1068 log2str("Param ", id, " not found in ", li));
1069 }
1070 return valueof(parameter);
1071}
1072
1073function f_sip_param_get_value(GenericParam_List li,
1074 template (present) charstring id := ?)
1075return template (omit) charstring {
1076 var template (omit) GenericParam parameter;
1077 parameter := f_sip_param_find(li, id);
1078 if (istemplatekind(parameter, "omit")) {
1079 return omit;
1080 }
1081 return parameter.paramValue;
1082}
1083
1084function f_sip_param_get_value_or_fail(GenericParam_List li,
1085 template (present) charstring id := ?)
1086return template (omit) charstring {
1087 var GenericParam parameter;
1088 parameter := f_sip_param_find_or_fail(li, id);
1089 return parameter.paramValue;
1090}
1091
1092function f_sip_param_get_value_present_or_fail(GenericParam_List li,
1093 template (present) charstring id := ?)
1094return charstring {
1095 var GenericParam parameter;
1096 parameter := f_sip_param_find_or_fail(li, id);
1097 if (not ispresent(parameter.paramValue)) {
1098 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1099 log2str("Param ", id, " value not present in ", li));
1100 }
1101 return parameter.paramValue;
1102}
1103
1104function f_sip_param_match_value(GenericParam_List li,
1105 template (present) charstring id := ?,
1106 template charstring exp_paramValue := *)
1107return boolean {
1108 var template (omit) charstring val;
1109 val := f_sip_param_get_value_or_fail(li, id);
1110 if (istemplatekind(val, "omit")) {
1111 return istemplatekind(val, "omit") or istemplatekind(val, "*");
1112 }
1113 return match(valueof(val), exp_paramValue);
1114}
1115
1116function f_sip_param_match_value_or_fail(GenericParam_List li,
1117 template (present) charstring id := ?,
1118 template charstring exp_paramValue := *)
1119{
1120 var template (omit) charstring val := f_sip_param_get_value_or_fail(li, id);
1121 if (istemplatekind(val, "omit")) {
1122 if (istemplatekind(val, "omit") or istemplatekind(val, "*")) {
1123 return;
1124 } else {
1125 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1126 log2str("Param ", id, " match failed: val ", val,
1127 " vs exp ", exp_paramValue));
1128 }
1129 }
1130 if (not match(valueof(val), exp_paramValue)) {
1131 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1132 log2str("Param ", id, " match failed: val ", val,
1133 " vs exp ", exp_paramValue));
1134 }
1135}
1136
1137function f_sip_param_remove(template (omit) GenericParam_List li_tpl, charstring id)
1138return GenericParam_List {
1139 var integer i;
1140 var GenericParam_List li;
1141 var GenericParam_List new_li := {};
1142
1143 if (istemplatekind(li_tpl, "omit")) {
1144 return {};
1145 }
1146
1147 li := valueof(li_tpl);
1148 for (i := 0; i < lengthof(li); i := i + 1) {
1149 if (not ispresent(li[i]) or
1150 not match(li[i].id, id)) {
1151 new_li := new_li & {li[i]};
1152 }
1153 }
1154 return new_li;
1155}
1156
1157function f_sip_param_set(template (omit) GenericParam_List li_tpl, charstring id, charstring val)
1158return GenericParam_List {
1159 var integer i;
1160 var GenericParam_List li;
1161 var GenericParam_List new_li := {};
1162 var boolean found := false;
1163
1164 if (istemplatekind(li_tpl, "omit")) {
1165 return { valueof(ts_Param(id, val)) };
1166 }
1167
1168 li := valueof(li_tpl);
1169 for (i := 0; i < lengthof(li); i := i + 1) {
1170 if (not ispresent(li[i]) or
1171 not match(li[i].id, id)) {
1172 new_li := new_li & {li[i]};
1173 continue;
1174 }
1175 new_li := new_li & { valueof(ts_Param(li[i].id, val)) };
1176 found := true;
1177 }
1178
1179 if (not found) {
1180 new_li := new_li & { valueof(ts_Param(id, val)) };
1181 }
1182 return new_li;
1183}
1184
1185/* Make sure string is quoted. */
1186function f_sip_str_quote(template (value) charstring val) return charstring {
1187 var charstring str := valueof(val);
1188 if (lengthof(str) == 0) {
1189 return "";
1190 }
1191
1192 if (str[0] != "\"") {
1193 return "\"" & str & "\"";
1194 }
1195 return str;
1196}
1197
1198/* Make sure string is unquoted.
1199 * Similar to unq() in RFC 2617 */
1200function f_sip_str_unquote(template (value) charstring val) return charstring {
1201 var charstring str := valueof(val);
1202 var integer len := lengthof(str);
1203
1204 if (len <= 1) {
1205 return str;
1206 }
1207
1208 if (str[0] == "\"" and str[len - 1] == "\"") {
1209 return substr(str, 1, len - 2);
1210 }
1211 return str;
1212}
1213
1214/* RFC 2617 3.2.2.2 A1 */
1215function f_sip_digest_A1(charstring user, charstring realm, charstring password) return charstring {
1216
1217 /* RFC 2617 3.2.2.2 A1 */
1218 var charstring A1 := f_sip_str_unquote(user) & ":" &
1219 f_sip_str_unquote(realm) & ":" &
1220 password;
1221 var charstring digestA1 := f_str_tolower(f_calculateMD5(A1));
1222 log("A1: md5('", A1, "') = ", digestA1);
1223 return digestA1;
1224}
1225
1226/* RFC 2617 3.2.2.2 A2 */
1227function f_sip_digest_A2(charstring method, charstring uri) return charstring {
1228
1229 var charstring A2 := method & ":" & uri
1230 var charstring digestA2 := f_str_tolower(f_calculateMD5(A2));
1231 log("A2: md5('", A2, "') = ", digestA2);
1232 return digestA2;
1233}
1234
1235/* RFC 2617 3.2.2.1 Request-Digest */
1236function f_sip_digest_RequestDigest(charstring digestA1, charstring nonce,
1237 charstring nc, charstring cnonce,
1238 charstring qop, charstring digestA2) return charstring {
1239 var charstring digest_data := f_sip_str_unquote(nonce) & ":" &
1240 nc & ":" &
1241 cnonce & ":" &
1242 f_sip_str_unquote(qop) & ":" &
1243 digestA2;
1244 var charstring req_digest := f_sip_digest_KD(digestA1, digest_data);
1245 log("Request-Digest: md5('", digestA1, ":", digest_data ,"') = ", req_digest);
1246 return req_digest;
1247}
1248
1249/* RFC 2617 3.2.1 The WWW-Authenticate Response Header
1250 * KD(secret, data) = H(concat(secret, ":", data))
1251 */
1252function f_sip_digest_KD(charstring secret, charstring data) return charstring {
1253 return f_str_tolower(f_calculateMD5(secret & ":" & data));
1254}
1255
1256/* Digest Auth: RFC 2617 */
1257function f_sip_digest_gen_Authorization(WwwAuthenticate www_authenticate,
1258 charstring user, charstring password,
1259 charstring method, charstring uri,
1260 charstring cnonce := "0a4f113b", integer nc_int := 1) return Authorization {
1261 var CommaParam_List digestCln;
1262 var template (value) Authorization authorization;
1263 var template (value) Credentials cred;
1264 var template (omit) GenericParam rx_param;
1265
1266 digestCln := www_authenticate.challenge[0].digestCln;
1267
1268 var charstring algorithm;
1269 rx_param := f_sip_param_find(digestCln, "algorithm");
1270 if (istemplatekind(rx_param, "omit")) {
1271 /* Assume MD5 if not set */
1272 algorithm := "MD5"
1273 } else {
1274 algorithm := valueof(rx_param.paramValue);
1275 if (f_strstr(algorithm, "MD5") == -1) {
1276 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1277 log2str("Unexpected algorithm: ", algorithm));
1278 }
1279 }
1280
1281 var charstring realm := f_sip_param_get_value_present_or_fail(digestCln, "realm");
1282 var charstring nonce := f_sip_param_get_value_present_or_fail(digestCln, "nonce");
1283 var charstring opaque := f_sip_param_get_value_present_or_fail(digestCln, "opaque");
1284 var charstring qop := f_sip_param_get_value_present_or_fail(digestCln, "qop");
1285
1286 if (f_strstr(qop, "auth") == -1) {
1287 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected qop: ", qop));
1288 }
1289 var charstring selected_qop := "auth";
1290
1291 /* RFC 2617 3.2.2.2 A1 */
1292 var charstring digestA1 := f_sip_digest_A1(user, realm, password);
1293 /* RFC 2617 3.2.2.3 A2 */
1294 var charstring digestA2 := f_sip_digest_A2(method, uri);
1295
1296 /* RFC 2617 3.2.2.1 Request-Digest */
1297 var charstring nc := f_str_tolower(hex2str(int2hex(nc_int, 8)));
1298 var charstring req_digest := f_sip_digest_RequestDigest(digestA1, nonce,
1299 nc, cnonce,
1300 selected_qop, digestA2);
1301
1302 cred := ts_Credentials_DigestResponseMD5(user, realm, nonce,
1303 uri, req_digest,
1304 opaque, algorithm, selected_qop, cnonce, nc);
1305
1306 authorization := ts_Authorization(cred);
1307 return valueof(authorization);
1308}
1309
1310/* RFC 2617 3.5 Example */
1311function f_sip_digest_selftest() {
1312/*
1313The following example assumes that an access-protected document is
1314being requested from the server via a GET request. The URI of the
1315document is "http://www.nowhere.org/dir/index.html". Both client and
1316server know that the username for this document is "Mufasa", and the
1317password is "Circle Of Life" (with one space between each of the
1318three words).
1319
1320HTTP/1.1 401 Unauthorized
1321WWW-Authenticate: Digest
1322 realm="testrealm@host.com",
1323 qop="auth,auth-int",
1324 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
1325 opaque="5ccc069c403ebaf9f0171e9517f40e41"
1326
1327Authorization: Digest username="Mufasa",
1328 realm="testrealm@host.com",
1329 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
1330 uri="/dir/index.html",
1331 qop=auth,
1332 nc=00000001,
1333 cnonce="0a4f113b",
1334 response="6629fae49393a05397450978507c4ef1",
1335 opaque="5ccc069c403ebaf9f0171e9517f40e41"
1336*/
1337 var template (value) CommaParam_List digestCln := {
1338 ts_Param("realm", f_sip_str_quote("testrealm@host.com")),
1339 ts_Param("qop", f_sip_str_quote("auth,auth-int")),
1340 ts_Param("nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093")),
1341 ts_Param("opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41"))
1342 };
1343 var template (value) WwwAuthenticate www_authenticate :=
1344 ts_WwwAuthenticate( { ts_Challenge_digestCln(digestCln) } )
1345
1346 var Authorization authorization :=
1347 f_sip_digest_gen_Authorization(valueof(www_authenticate),
1348 "Mufasa",
1349 "Circle Of Life",
1350 "GET",
1351 "/dir/index.html",
1352 cnonce := "0a4f113b",
1353 nc_int := 1);
1354
1355 var CommaParam_List digestResp := authorization.body.digestResponse;
1356 f_sip_param_match_value_or_fail(digestResp, "realm", f_sip_str_quote("testrealm@host.com"));
1357 f_sip_param_match_value_or_fail(digestResp, "nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093"));
1358 f_sip_param_match_value_or_fail(digestResp, "uri", f_sip_str_quote("/dir/index.html"));
1359 f_sip_param_match_value_or_fail(digestResp, "qop", "auth");
1360 f_sip_param_match_value_or_fail(digestResp, "nc", "00000001");
1361 f_sip_param_match_value_or_fail(digestResp, "cnonce", f_sip_str_quote("0a4f113b"));
1362 f_sip_param_match_value_or_fail(digestResp, "response", f_sip_str_quote("6629fae49393a05397450978507c4ef1"));
1363 f_sip_param_match_value_or_fail(digestResp, "opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41"));
1364}
1365
Pau Espin Pedrol6052a342024-03-28 20:20:46 +01001366/* RFC 3261 8.1.1.5:
1367 * "The sequence number value MUST be expressible as a 32-bit unsigned integer
1368 * and MUST be less than 2**31."
1369 */
1370function f_sip_rand_seq_nr() return integer {
1371 /* 2**31 = 2147483648 */
1372 return f_rnd_int(2147483648)
1373}
Harald Welteb0d93602018-03-20 18:09:34 +01001374
Pau Espin Pedrol7011bf42024-04-08 17:56:58 +02001375function f_sip_next_seq_nr(integer seq_nr) return integer {
1376 return (seq_nr + 1) mod 2147483648;
1377}
1378
1379function f_sip_Request_inc_seq_nr(inout template (value) PDU_SIP_Request req) {
1380 req.msgHeader.cSeq.seqNumber := f_sip_next_seq_nr(valueof(req.msgHeader.cSeq.seqNumber));
1381}
1382
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001383function f_sip_rand_tag() return charstring {
Pau Espin Pedrol95ad6a02024-04-18 16:52:46 +02001384 /* Tags shall have at least 32 bit of randomness */
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001385 var integer rnd_int := f_rnd_int(4294967296);
Pau Espin Pedrol95ad6a02024-04-18 16:52:46 +02001386 /* Make collisions harder by appending time to the final string: */
1387 var integer ts_int := f_time_ms() mod 4294967296;
1388 return hex2str(int2hex(rnd_int, 8)) & "-" & hex2str(int2hex(ts_int, 8));
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001389}
1390
1391/* Generate a "branch" tag value.
1392 * RFC 3261 p.105 section 8:
1393 * "A common way to create this value is to compute a
1394 * cryptographic hash of the To tag, From tag, Call-ID header
1395 * field, the Request-URI of the request received (before
1396 * translation), the topmost Via header, and the sequence number
1397 * from the CSeq header field, in addition to any Proxy-Require
1398 * and Proxy-Authorization header fields that may be present. The
1399 * algorithm used to compute the hash is implementation-dependent,
1400 * but MD5 (RFC 1321 [35]),expressed in hexadecimal, is a reasonable
1401 * choice."
1402 * See also Section 8.1.1.7:
1403 * "The branch ID inserted by an element compliant with this
1404 * specification MUST always begin with the characters "z9hG4bK"."
1405 */
1406const charstring sip_magic_cookie := "z9hG4bK";
1407function f_sip_gen_branch(charstring tag_to,
1408 charstring tag_from,
1409 charstring tag_call_id,
1410 integer cseq) return charstring {
1411 var charstring str := tag_to & tag_from & tag_call_id & int2str(cseq);
1412 var charstring hash := f_calculateMD5(str);
1413 var charstring branch := sip_magic_cookie & hash;
1414 return branch;
1415}
1416
1417function f_sip_HostPort_to_str(HostPort host_port) return charstring {
1418 var charstring str := "";
1419 if (ispresent(host_port.host)) {
1420 str := host_port.host;
1421 }
1422 if (ispresent(host_port.portField)) {
1423 str := str & ":" & int2str(host_port.portField);
1424 }
1425 return str;
1426}
1427
1428function f_sip_SipUrl_to_str(SipUrl uri) return charstring {
Pau Espin Pedrolb0dbf7a2024-05-22 18:12:15 +02001429 var charstring str := uri.scheme & ":";
1430 if (ispresent(uri.userInfo)) {
1431 str := str & uri.userInfo.userOrTelephoneSubscriber & "@";
1432 }
1433 str := str & f_sip_HostPort_to_str(uri.hostPort);
Pau Espin Pedrol05eaa1a2024-04-02 12:56:26 +02001434 return str;
1435}
1436
1437function f_sip_NameAddr_to_str(NameAddr naddr) return charstring {
1438 if (ispresent(naddr.displayName)) {
1439 return naddr.displayName & " <" & f_sip_SipUrl_to_str(naddr.addrSpec) & ">";
1440 } else {
1441 return f_sip_SipUrl_to_str(naddr.addrSpec);
1442 }
1443}
1444
1445function f_sip_SipAddr_to_str(SipAddr sip_addr) return charstring {
1446 if (ischosen(sip_addr.addr.nameAddr)) {
1447 return f_sip_NameAddr_to_str(sip_addr.addr.nameAddr);
1448 } else {
1449 return f_sip_SipUrl_to_str(sip_addr.addr.addrSpecUnion);
1450 }
1451}
1452
Harald Welteb0d93602018-03-20 18:09:34 +01001453}