asterisk: Use Action PJSIPAccessNetworkInfo
Validate P-Access-Network-Info should only be present in 2nd REGISTER
sent over ipsec.
Change-Id: I2759d12caeaca81a9224997a29541c325d65fe30
diff --git a/asterisk/AMI_Functions.ttcn b/asterisk/AMI_Functions.ttcn
index 9fbe973..4969905 100644
--- a/asterisk/AMI_Functions.ttcn
+++ b/asterisk/AMI_Functions.ttcn
@@ -28,6 +28,7 @@
const charstring AMI_FIELD_ACTION := "Action";
const charstring AMI_FIELD_ACTION_ID := "ActionID";
const charstring AMI_FIELD_EVENT := "Event";
+const charstring AMI_FIELD_INFO := "Info";
const charstring AMI_FIELD_USERNAME := "Username";
const charstring AMI_FIELD_SECRET := "Secret";
const charstring AMI_FIELD_RESPONSE := "Response";
@@ -79,6 +80,8 @@
template (value) AMI_Field
ts_AMI_Field_Event(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_EVENT, val);
template (value) AMI_Field
+ts_AMI_Field_Info(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_INFO, val);
+template (value) AMI_Field
ts_AMI_Field_Username(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_USERNAME, val);
template (value) AMI_Field
ts_AMI_Field_Secret(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_SECRET, val);
@@ -93,6 +96,8 @@
template (present) AMI_Field
tr_AMI_Field_Event(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_EVENT, val);
template (present) AMI_Field
+tr_AMI_Field_Info(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_INFO, val);
+template (present) AMI_Field
tr_AMI_Field_Username(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_USERNAME, val);
template (present) AMI_Field
tr_AMI_Field_Secret(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_SECRET, val);
@@ -139,6 +144,23 @@
tr_AMI_Field_Secret(secret)
);
+/* Action: PJSIPAccessNetworkInfo
+ * Registration: volte_ims
+ * Info: 3GPP-E-UTRAN-FDD; utran-cell-id-3gpp=2380100010000101
+ */
+template (value) AMI_Msg
+ts_AMI_Action_PJSIPAccessNetworkInfo(template (value) charstring registration := "volte_ims",
+ template (value) charstring info := "",
+ template (value) charstring action_id := "0001") := {
+ ts_AMI_Field_Action("PJSIPAccessNetworkInfo"),
+ ts_AMI_Field_ActionId(action_id),
+ ts_AMI_Field_Registration(registration),
+ ts_AMI_Field_Info(info)
+};
+function f_ami_gen_PJSIPAccessNetworkInfo_Info_EUTRAN(charstring uli_str) return charstring {
+ return "3GPP-E-UTRAN-FDD; utran-cell-id-3gpp=" & uli_str;
+}
+
/* Action: PJSIPRegister
* ActionID: <value>
* Registration: volte_ims
@@ -508,6 +530,13 @@
f_ami_transceive_match_response_success(pt, ts_AMI_Action_Login(username, secret, reg_action_id));
}
+function f_ami_action_PJSIPAccessNetworkInfo(AMI_Msg_PT pt,
+ template (value) charstring registration,
+ template (value) charstring info) {
+ var charstring reg_action_id := f_gen_action_id();
+ f_ami_transceive_match_response_success(pt, ts_AMI_Action_PJSIPAccessNetworkInfo(registration, info, reg_action_id));
+}
+
function f_ami_action_PJSIPRegister(AMI_Msg_PT pt, charstring register) {
var charstring reg_action_id := f_gen_action_id();
f_ami_transceive_match_response_success(pt, ts_AMI_Action_PJSIPRegister(register, reg_action_id));
diff --git a/asterisk/Asterisk_Tests.ttcn b/asterisk/Asterisk_Tests.ttcn
index a71bcad..df5904b 100644
--- a/asterisk/Asterisk_Tests.ttcn
+++ b/asterisk/Asterisk_Tests.ttcn
@@ -376,6 +376,12 @@
f_sleep(1.0);
/* Clear events: */
AMI_CLIENT.clear;
+
+ /* Announce network information, this should usually happen when UE
+ * becomes attached to network and before IMS APN is set up: */
+ f_ami_action_PJSIPAccessNetworkInfo(AMI_CLIENT, mp_volte_ims_outbound_registration,
+ f_ami_gen_PJSIPAccessNetworkInfo_Info_EUTRAN(pars.uli_str));
+
/* Trigger registration: */
f_ami_action_PJSIPRegister(AMI_CLIENT, mp_volte_ims_outbound_registration);
/* TODO: Rx "Event: AuthRequest" */
diff --git a/asterisk/IMS_ConnectionHandler.ttcn b/asterisk/IMS_ConnectionHandler.ttcn
index d1e3185..0d11922 100644
--- a/asterisk/IMS_ConnectionHandler.ttcn
+++ b/asterisk/IMS_ConnectionHandler.ttcn
@@ -66,6 +66,8 @@
charstring user,
charstring display_name,
charstring password,
+ /* Expected User-Location-Info in P-Access-Network-Info */
+ charstring uli_str,
octetstring rand,
octetstring autn,
charstring ipsec_auth_key,
@@ -148,6 +150,7 @@
user := user,
display_name := f_sip_str_quote(display_name),
password := password,
+ uli_str := "2380100010000101",
/* The Nonce field is the Base64 encoded version of the RAND value and concatenated with the AUTN: */
rand := '14987631f65f8e3788a0798b6ebcd08e'O,
autn := 'f6e19a7ccb028000a06b19c9544516e5'O,
@@ -272,6 +275,37 @@
be indicated by adding a “video” media feature tag to the contact: header." */
}
+/* Validate P-Access-Network-Info: RFC7315 6.4 */
+private function f_ims_validate_register_P_Access_Network_info(PDU_SIP_Request req,
+ boolean exp_present := true) runs on IMS_ConnHdlr
+
+{
+ if (not exp_present) {
+ if (ispresent(g_rx_sip_req.msgHeader.p_access_network_info)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str(g_name & ": Received unexpected [rfc7315 6.4] P-Access-Info := ",
+ g_rx_sip_req.msgHeader.p_access_network_info));
+ }
+ return;
+ }
+
+ /* exp_present: */
+ var template (present) P_Access_Network_Info expl_tmpl :=
+ tr_P_Access_Network_Info({ tr_Access_net_spec_EUTRAN(g_pars.uli_str) });
+
+ if (not ispresent(g_rx_sip_req.msgHeader.p_access_network_info)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str(g_name & ": Received no P-Access-Info vs exp := ",
+ expl_tmpl));
+ }
+ if (not match(g_rx_sip_req.msgHeader.p_access_network_info, expl_tmpl)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str(g_name & ": Received unexpected P-Access-Info := ",
+ g_rx_sip_req.msgHeader.p_access_network_info,
+ "\nvs exp := ", expl_tmpl));
+ }
+}
+
private function f_ims_parse_security_client(Security_client security_client) runs on IMS_ConnHdlr
{
var boolean found := false;
@@ -390,6 +424,16 @@
contact := g_rx_sip_req.msgHeader.contact;
f_ims_validate_register_contact(contact);
+ /* Validate P-Access-Network-Info: rfc7315 6.4:
+ * "3GPP will use the P-Access-Network-Info header field to
+ * carry relatively sensitive information like the cell ID. Therefore,
+ * the information MUST NOT be sent outside of the 3GPP domain.""
+ * [...] "the sensitive information carried in the
+ * P-Access-Network-Info header field MUST NOT be sent in any initial
+ * unauthenticated and unprotected requests (e.g., REGISTER)."
+ */
+ f_ims_validate_register_P_Access_Network_info(g_rx_sip_req, exp_present := false);
+
/* TODO: Validate "Expires" is 600000 */
/* Tx 100 Tyring */
@@ -490,6 +534,9 @@
userAgent := omit);
SIP.send(tx_resp);
+ /* Validate P-Access-Network-Info: */
+ f_ims_validate_register_P_Access_Network_info(g_rx_sip_req, exp_present := true);
+
/* Tx 200 OK */
to_addr.params := f_sip_param_set(to_addr.params, "tag", f_sip_rand_tag());
tx_resp := ts_SIP_Response(sip_call_id,
diff --git a/library/SIP_Templates.ttcn b/library/SIP_Templates.ttcn
index 7ef49cf..7da56bc 100644
--- a/library/SIP_Templates.ttcn
+++ b/library/SIP_Templates.ttcn
@@ -224,6 +224,23 @@
deltaSec := deltaSec
}
+// [RFC3455 5.4] + 3GPP 24.229 V8.7.0
+template (present) Access_net_spec tr_Access_net_spec(template (present) charstring access_type := ?,
+ template SemicolonParam_List access_info := *) := {
+ access_type := access_type,
+ access_info := access_info
+}
+template (present) Access_net_spec tr_Access_net_spec_EUTRAN(template (present) charstring uli_str := ?) := {
+ access_type := "3GPP-E-UTRAN-FDD",
+ access_info := {tr_Param("utran-cell-id-3gpp", uli_str)}
+}
+
+// [RFC3455 5.4] + 3GPP 24.229 V8.7.0
+template (present) P_Access_Network_Info tr_P_Access_Network_Info(template (present) Access_net_spec_list access_net_specs := ?) := {
+ fieldName := P_ACCESS_NETWORK_INFO,
+ access_net_specs := access_net_specs
+}
+
// [20.32]
template (value) Require ts_Require(template (value) OptionTag_List optionsTags := {}) := {