pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/36340?usp=email )
Change subject: epdg: Trigger AAR+AAA upon rx of RAR ......................................................................
epdg: Trigger AAR+AAA upon rx of RAR
Related: OS#6406 Change-Id: I478b781e65eb5dd0cce5b51c75a1aa592b6555bc --- M src/aaa_diameter_swm.erl M src/aaa_ue_fsm.erl M src/epdg_diameter_swm.erl M src/epdg_ue_fsm.erl 4 files changed, 150 insertions(+), 17 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-epdg refs/changes/40/36340/1
diff --git a/src/aaa_diameter_swm.erl b/src/aaa_diameter_swm.erl index fadff7e..0f5e279 100644 --- a/src/aaa_diameter_swm.erl +++ b/src/aaa_diameter_swm.erl @@ -17,6 +17,7 @@ -export([rx_der_auth_request/4, rx_der_auth_compl_request/2, rx_reauth_answer/2, + rx_auth_request/1, rx_session_termination_request/1, rx_abort_session_answer/1]). -export([tx_dea_auth_response/2, @@ -65,6 +66,10 @@ rx_reauth_answer(Imsi, Result) -> gen_server:cast(?SERVER, {raa, Imsi, Result}).
+% 3GPP TS 29.273 7.2.2.1.3 Diameter-AA-Request (AAR) Command +rx_auth_request(Imsi) -> + gen_server:cast(?SERVER, {aar, Imsi}). + rx_session_termination_request(Imsi) -> gen_server:cast(?SERVER, {str, Imsi}).
@@ -98,6 +103,22 @@ end, {noreply, State};
+handle_cast({aar, Imsi}, State) -> + case aaa_ue_fsm:get_pid_by_imsi(Imsi) of + Pid when is_pid(Pid) -> + case aaa_ue_fsm:ev_rx_swm_auth_request(Pid) of + ok -> + epdg_diameter_swm:rx_auth_answer(Imsi, ok); + _ -> + RC_UNABLE_TO_COMPLY=5012, + epdg_diameter_swm:rx_auth_answer(Imsi, {error, RC_UNABLE_TO_COMPLY}) + end; + undefined -> + RC_USER_UNKNOWN=5030, + epdg_diameter_swm:rx_auth_answer(Imsi, {error, RC_USER_UNKNOWN}) + end, + {noreply, State}; + handle_cast({str, Imsi}, State) -> case aaa_ue_fsm:get_pid_by_imsi(Imsi) of Pid when is_pid(Pid) -> diff --git a/src/aaa_ue_fsm.erl b/src/aaa_ue_fsm.erl index abbe40e..968c7bd 100644 --- a/src/aaa_ue_fsm.erl +++ b/src/aaa_ue_fsm.erl @@ -43,7 +43,8 @@ -export([init/1,callback_mode/0,terminate/3]). -export([get_server_name_by_imsi/1, get_pid_by_imsi/1]). -export([ev_rx_swm_der_auth_req/2, ev_rx_swm_der_auth_compl/2, - ev_rx_swm_reauth_answer/2, ev_rx_swm_str/1, ev_rx_swm_asa/1, + ev_rx_swm_reauth_answer/2, ev_rx_swm_auth_request/1, + ev_rx_swm_str/1, ev_rx_swm_asa/1, ev_rx_swx_maa/2, ev_rx_swx_saa/2, ev_rx_swx_ppr/2, ev_rx_swx_rtr/1, ev_rx_s6b_aar/2, ev_rx_s6b_str/1, ev_rx_s6b_raa/2, ev_rx_s6b_asa/2]). -export([state_new/3, @@ -104,6 +105,15 @@ {error, Err} end.
+ev_rx_swm_auth_request(Pid) -> + lager:info("ue_fsm ev_rx_swm_auth_request~n", []), + try + gen_statem:call(Pid, rx_swm_auth_request) + catch + exit:Err -> + {error, Err} + end. + ev_rx_swm_der_auth_compl(Pid, Apn) -> lager:info("ue_fsm ev_rx_swm_der_auth_compl~n", []), try @@ -371,6 +381,11 @@ %% SWx PPA was already answered immediately when PPR was received, nothing to do here. {keep_state, Data, [{reply,From,ok}]};
+state_authenticated({call, From}, rx_swm_auth_request, Data) -> + lager:info("ue_fsm state_authenticated event=rx_swm_auth_request, ~p~n", [Data]), + %% answer is trnamsitted when returning ok: + {keep_state, Data, [{reply,From,ok}]}; + state_authenticated({call, From}, {rx_s6b_raa, Result}, Data) -> lager:info("ue_fsm state_authenticated event=rx_s6b_raa ~p, ~p~n", [Result, Data]), %% SWx PPA was already answered immediately when PPR was received, nothing to do here. diff --git a/src/epdg_diameter_swm.erl b/src/epdg_diameter_swm.erl index cdf572f..ba5893c 100644 --- a/src/epdg_diameter_swm.erl +++ b/src/epdg_diameter_swm.erl @@ -15,13 +15,15 @@ -export([code_change/3, terminate/2]).
-export([tx_der_auth_request/4, - tx_reauth_answer/2, tx_der_auth_compl_request/2, + tx_reauth_answer/2, + tx_auth_req/1, tx_session_termination_request/1, tx_abort_session_answer/1]). -export([rx_dea_auth_response/2, rx_dea_auth_compl_response/2, rx_reauth_request/1, + rx_auth_answer/2, rx_session_termination_answer/2, rx_abort_session_request/1]).
@@ -56,6 +58,12 @@ ImsiStr = binary_to_list(Imsi), ok = gen_server:cast(?SERVER, {tx_dia, {der_auth_compl_req, ImsiStr, Apn}}).
+% 3GPP TS 29.273 7.1.2.2 +tx_auth_req(Imsi) -> + % In Diameter we use Imsi as strings, as done by diameter module. + ImsiStr = binary_to_list(Imsi), + ok = gen_server:cast(?SERVER, {tx_dia, {aar, ImsiStr}}). + % 3GPP TS 29.273 7.1.2.3 tx_session_termination_request(Imsi) -> % In Diameter we use Imsi as strings, as done by diameter module. @@ -73,6 +81,10 @@ ok = gen_server:cast(?SERVER, {rx_dia, {rar, Imsi}}).
%% Emulation from the wire (DIAMETER SWm), called from internal AAA Server: +rx_auth_answer(Imsi, Result) -> + ok = gen_server:cast(?SERVER, {rx_dia, {aaa, Imsi, Result}}). + +%% Emulation from the wire (DIAMETER SWm), called from internal AAA Server: rx_dea_auth_response(Imsi, Result) -> ok = gen_server:cast(?SERVER, {rx_dia, {dea_auth_resp, Imsi, Result}}).
@@ -113,6 +125,12 @@ aaa_diameter_swm:rx_der_auth_compl_request(Imsi, Apn), {noreply, State};
+% 3GPP TS 29.273 7.2.2.1.3 Diameter-AA-Request (AAR) Command +handle_cast({tx_dia, {aar, Imsi}}, State) -> + % we yet don't implement the Diameter SWm interface on the wire, we process the call internally: + aaa_diameter_swm:rx_auth_request(Imsi), + {noreply, State}; + handle_cast({tx_dia, {str, Imsi}}, State) -> % we yet don't implement the Diameter SWm interface on the wire, we process the call internally: aaa_diameter_swm:rx_session_termination_request(Imsi), @@ -155,6 +173,16 @@ end, {noreply, State};
+handle_cast({rx_dia, {aaa, ImsiStr, Result}}, State) -> + Imsi = list_to_binary(ImsiStr), + case epdg_ue_fsm:get_pid_by_imsi(Imsi) of + Pid when is_pid(Pid) -> + epdg_ue_fsm:received_swm_auth_answer(Pid, Result); + undefined -> + lager:notice("SWm Rx RAR: unknown swm-session ~p", [Imsi]) + end, + {noreply, State}; + handle_cast({rx_dia, {sta, ImsiStr, Result}}, State) -> Imsi = list_to_binary(ImsiStr), case epdg_ue_fsm:get_pid_by_imsi(Imsi) of diff --git a/src/epdg_ue_fsm.erl b/src/epdg_ue_fsm.erl index 8a0c16e..4a090e9 100644 --- a/src/epdg_ue_fsm.erl +++ b/src/epdg_ue_fsm.erl @@ -44,7 +44,8 @@ -export([get_server_name_by_imsi/1, get_pid_by_imsi/1]). -export([auth_request/2, lu_request/1, tunnel_request/2, purge_ms_request/1, cancel_location_result/1]). --export([received_swm_reauth_request/1, received_swm_dea_auth_response/2, received_swm_dea_auth_compl_response/2, +-export([received_swm_reauth_request/1, received_swm_dea_auth_response/2, + received_swm_dea_auth_compl_response/2, received_swm_auth_answer/2, received_swm_session_termination_answer/2, received_swm_abort_session_request/1]). -export([received_gtpc_create_session_response/2, received_gtpc_delete_session_response/2, received_gtpc_delete_bearer_request/1]). -export([state_new/3, @@ -69,7 +70,9 @@ pgw_rem_addr_list = [] :: list(), tun_pdp_ctx :: epdg_tun_pdp_ctx, tear_down_gsup_needed = false :: boolean(), %% need to send GSUP PurgeMSResp after STR+STA? - tear_down_gsup_cause = 0 :: integer() + tear_down_gsup_cause = 0 :: integer(), + tear_down_s2b_needed = false :: boolean(), %% need to send S2b DeleteSessionReq + tear_down_tx_swm_asa_needed = false :: boolean() %% need to send SWm ASA }).
get_server_name_by_imsi(Imsi) -> @@ -147,6 +150,15 @@ {error, Err} end.
+received_swm_auth_answer(Pid, Result) -> +lager:info("ue_fsm received_swm_auth_answer~n", []), +try +gen_statem:call(Pid, {received_swm_auth_answer, Result}) +catch +exit:Err -> + {error, Err} +end. + received_swm_dea_auth_response(Pid, Result) -> lager:info("ue_fsm received_swm_dea_auth_response ~p~n", [Result]), try @@ -342,13 +354,26 @@ state_authenticated({call, From}, received_swm_reauth_request, Data) -> lager:info("ue_fsm state_authenticated event=received_swm_reauth_request, ~p~n", [Data]), epdg_diameter_swm:tx_reauth_answer(Data#ue_fsm_data.imsi, #epdg_dia_rc{result_code = 2001}), - % TODO: 3GPP TS 29.273 7.1.2.5.1: + % 3GPP TS 29.273 7.1.2.5.1: % Upon receiving the re-authorization request, the ePDG shall immediately invoke the authorization procedure % specified in 7.1.2.2 for the session indicated in the request. This procedure is based on the Diameter % commands AA-Request (AAR) and AA-Answer (AAA) specified in IETF RFC 4005 [4]. Information % element contents for these messages are shown in tables 7.1.2.2.1/1 and 7.1.2.2.1/2. + epdg_diameter_swm:tx_auth_req(Data#ue_fsm_data.imsi), {keep_state, Data, [{reply,From,ok}]};
+ +state_authenticated({call, From}, {received_swm_auth_answer, Result}, Data) -> + lager:info("ue_fsm state_authenticated event=received_swm_auth_answer(~p), ~p~n", [Result, Data]), + case Result of + ok -> + {keep_state, Data, [{reply,From,ok}]}; + _ -> + Data1 = Data#ue_fsm_data{tear_down_gsup_needed = false, + tear_down_s2b_needed = false}, + {next_state, state_dereg_net_initiated_wait_cancel_location_res, Data1, [{reply,From,ok}]} + end; + state_authenticated({call, From}, purge_ms_request, Data) -> lager:info("ue_fsm state_authenticated event=purge_ms_request, ~p~n", [Data]), Data1 = Data#ue_fsm_data{tear_down_gsup_needed = true}, @@ -397,7 +422,7 @@ end;
state_wait_create_session_resp({call, From}, Event, Data) -> - lager:error("ue_fsm state_wait_delete_session_resp: Unexpected call event ~p, ~p~n", [Event, Data]), + lager:error("ue_fsm state_wait_create_session_resp: Unexpected call event ~p, ~p~n", [Event, Data]), {keep_state, Data, [{reply,From,{error,unexpected_event}}]};
state_wait_create_session_resp(state_timeout, create_session_timeout, Data) -> @@ -421,13 +446,28 @@ state_active({call, From}, received_swm_reauth_request, Data) -> lager:info("ue_fsm state_active event=received_swm_reauth_request, ~p~n", [Data]), epdg_diameter_swm:tx_reauth_answer(Data#ue_fsm_data.imsi, #epdg_dia_rc{result_code = 2001}), - % TODO: 3GPP TS 29.273 7.1.2.5.1: + % 3GPP TS 29.273 7.1.2.5.1: % Upon receiving the re-authorization request, the ePDG shall immediately invoke the authorization procedure % specified in 7.1.2.2 for the session indicated in the request. This procedure is based on the Diameter % commands AA-Request (AAR) and AA-Answer (AAA) specified in IETF RFC 4005 [4]. Information % element contents for these messages are shown in tables 7.1.2.2.1/1 and 7.1.2.2.1/2. + epdg_diameter_swm:tx_auth_req(Data#ue_fsm_data.imsi), {keep_state, Data, [{reply,From,ok}]};
+state_active({call, From}, {received_swm_auth_answer, Result}, Data) -> + lager:info("ue_fsm state_active event=received_swm_auth_answer(~p), ~p~n", [Result, Data]), + case Result of + ok -> + {keep_state, Data, [{reply,From,ok}]}; + _ -> + gtp_u_tun:delete_pdp_context(Data#ue_fsm_data.tun_pdp_ctx), + Data1 = Data#ue_fsm_data{tun_pdp_ctx = undefined, + tear_down_gsup_needed = false, + tear_down_s2b_needed = true, + tear_down_tx_swm_asa_needed = false}, + {next_state, state_dereg_net_initiated_wait_cancel_location_res, Data1, [{reply,From,ok}]} + end; + state_active({call, From}, purge_ms_request, Data) -> lager:info("ue_fsm state_active event=purge_ms_request, ~p~n", [Data]), gtp_u_tun:delete_pdp_context(Data#ue_fsm_data.tun_pdp_ctx), @@ -440,14 +480,20 @@ state_active({call, From}, received_gtpc_delete_bearer_request, Data) -> lager:info("ue_fsm state_active event=received_gtpc_delete_bearer_request, ~p~n", [Data]), gtp_u_tun:delete_pdp_context(Data#ue_fsm_data.tun_pdp_ctx), - Data1 = Data#ue_fsm_data{tun_pdp_ctx = undefined, tear_down_gsup_needed = false}, + Data1 = Data#ue_fsm_data{tun_pdp_ctx = undefined, + tear_down_gsup_needed = false, + tear_down_s2b_needed = false, + tear_down_tx_swm_asa_needed = false}, {next_state, state_dereg_pgw_initiated_wait_cancel_location_res, Data1, [{reply,From,ok}]};
%%% network (HSS/AAA) initiated de-registation requested: state_active({call, From}, received_swm_asr, Data) -> lager:info("ue_fsm state_active event=received_swm_asr, ~p~n", [Data]), gtp_u_tun:delete_pdp_context(Data#ue_fsm_data.tun_pdp_ctx), - Data1 = Data#ue_fsm_data{tun_pdp_ctx = undefined, tear_down_gsup_needed = false}, + Data1 = Data#ue_fsm_data{tun_pdp_ctx = undefined, + tear_down_gsup_needed = false, + tear_down_s2b_needed = true, + tear_down_tx_swm_asa_needed = true}, {next_state, state_dereg_net_initiated_wait_cancel_location_res, Data1, [{reply,From,ok}]};
state_active({call, From}, Event, Data) -> @@ -575,13 +621,26 @@ %% have triggered GTPCv1 Delete Session Req against PGW. %% Wait for GTPCv1 Delete Session Response, ssend SWm ASA to AAAA and terminate FSM. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +tx_swm_asa_if_needed(Data) -> + case Data#ue_fsm_data.tear_down_tx_swm_asa_needed of + true -> + epdg_diameter_swm:tx_abort_session_answer(Data#ue_fsm_data.imsi); + false -> lager:debug("Skip sending SWm ASA", []) + end. + state_dereg_net_initiated_wait_s2b_delete_session_resp(enter, _OldState, Data) -> - case epdg_gtpc_s2b:delete_session_req(Data#ue_fsm_data.imsi) of - ok -> - {keep_state, Data, {state_timeout,?TIMEOUT_VAL_WAIT_GTP_ANSWER,s2b_delete_session_timeout}}; - {error, Err} -> - epdg_diameter_swm:tx_abort_session_answer(Data#ue_fsm_data.imsi), - {stop, {error,Err}} + case Data#ue_fsm_data.tear_down_s2b_needed of + true -> + case epdg_gtpc_s2b:delete_session_req(Data#ue_fsm_data.imsi) of + ok -> + {keep_state, Data, {state_timeout,?TIMEOUT_VAL_WAIT_GTP_ANSWER,s2b_delete_session_timeout}}; + {error, Err} -> + tx_swm_asa_if_needed(Data), + {stop, {error,Err}} + end; + false -> + tx_swm_asa_if_needed(Data), + {stop, normal} end;
state_dereg_net_initiated_wait_s2b_delete_session_resp({call, From}, {received_gtpc_delete_session_response, _Resp = #gtp{version = v2, type = delete_session_response, ie = IEs}}, Data) -> @@ -589,7 +648,7 @@ #{{v2_cause,0} := CauseIE} = IEs, GtpCause = gtp_utils:enum_v2_cause(CauseIE#v2_cause.v2_cause), lager:debug("Cause: GTP_atom=~p -> GTP_int=~p~n", [CauseIE#v2_cause.v2_cause, GtpCause]), - epdg_diameter_swm:tx_abort_session_answer(Data#ue_fsm_data.imsi), + tx_swm_asa_if_needed(Data), {stop_and_reply, normal, [{reply,From,ok}], Data};
state_dereg_net_initiated_wait_s2b_delete_session_resp({call, From}, Event, Data) -> @@ -599,5 +658,5 @@
state_dereg_net_initiated_wait_s2b_delete_session_resp(state_timeout, s2b_delete_session_timeout, Data) -> lager:error("ue_fsm state_dereg_net_initiated_wait_s2b_delete_session_resp: Timeout ~p, ~p~n", [s2b_delete_session_timeout, Data]), - epdg_diameter_swm:tx_abort_session_answer(Data#ue_fsm_data.imsi), + tx_swm_asa_if_needed(Data), {stop, normal}.