pespin has submitted this change. ( https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35759?usp=email )
Change subject: AAA-Server: Process S6b, SWx requests async through new aaa_ue_fsm ...................................................................... AAA-Server: Process S6b, SWx requests async through new aaa_ue_fsm This will allow keeping per-UE session state, and for instance send a SAR(USER_DEREGISTRATION) towards HSS when all sessions from all interfaces (s6b, SWm) are terminated. Change-Id: I78ebda4679d0a2f3ecede94598e74b20c2ff8836 --- M src/aaa_diameter_s6b.erl M src/aaa_diameter_s6b_cb.erl M src/aaa_diameter_swm.erl M src/aaa_diameter_swx.erl M src/aaa_diameter_swx_cb.erl A src/aaa_ue_fsm.erl 6 files changed, 343 insertions(+), 72 deletions(-) Approvals: Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve pespin: Looks good to me, approved diff --git a/src/aaa_diameter_s6b.erl b/src/aaa_diameter_s6b.erl index 59b9679..2de479c 100644 --- a/src/aaa_diameter_s6b.erl +++ b/src/aaa_diameter_s6b.erl @@ -40,8 +40,8 @@ -behaviour(gen_server). --include_lib("diameter_3gpp_ts29_273_s6b.hrl"). -include_lib("diameter/include/diameter_gen_base_rfc6733.hrl"). +-include_lib("diameter_3gpp_ts29_273_s6b.hrl"). %% API Function Exports -export([start_link/0]). @@ -51,6 +51,7 @@ -export([code_change/3]). -export([multimedia_auth_request/6]). -export([server_assignment_request/3]). +-export([tx_aa_answer/2]). -export([test/0, test/1]). %% Diameter Application Definitions @@ -146,6 +147,10 @@ gen_server:call(?SERVER, {sar, {IMSI, Type, APN}}). +tx_aa_answer(Pid, ResultCode) -> + % handle_request(AAR) was spawned into its own process, and it's blocked waiting for AAA: + Pid ! {aaa, ResultCode}. + result_code_success(2001) -> ok; result_code_success(2002) -> ok; result_code_success(_) -> invalid_result_code. diff --git a/src/aaa_diameter_s6b_cb.erl b/src/aaa_diameter_s6b_cb.erl index ccfcaff..b03bce1 100644 --- a/src/aaa_diameter_s6b_cb.erl +++ b/src/aaa_diameter_s6b_cb.erl @@ -23,17 +23,17 @@ State. %% pick_peer/4 -pick_peer([_Peer | _], _, _SvcName, _State) -> - ?UNEXPECTED. +pick_peer([Peer | _], _, _SvcName, _State) -> + {ok, Peer}. %% prepare_request/3 - -prepare_request(_, _SvcName, _Peer) -> - ?UNEXPECTED. +prepare_request(_Req, _SvcName, _Peer) -> + lager:error("Unexpected prepare_request(): ~p~n", [_Req]), + ?UNEXPECTED. %% prepare_retransmit/3 -prepare_retransmit(_Packet, _SvcName, _Peer) -> - ?UNEXPECTED. +prepare_retransmit(Packet, SvcName, Peer) -> + prepare_request(Packet, SvcName, Peer). %% handle_answer/4 @@ -42,12 +42,12 @@ %% the former case, return in the latter. handle_answer(_Packet, _Request, _SvcName, _Peer) -> - ?UNEXPECTED. + ?UNEXPECTED. %% handle_error/4 handle_error(Reason, Request, _SvcName, _Peer) when is_list(Request) -> lager:error("Request error: ~p~n", [Reason]), - ?UNEXPECTED. + ?UNEXPECTED. % 3GPP TS 29.273 9.1.2.2 handle_request(#diameter_packet{msg = Req, errors = []}, _SvcName, {_, Caps}) when is_record(Req, 'AAR') -> @@ -59,21 +59,25 @@ 'Auth-Request-Type' = AuthReqType, 'User-Name' = [UserName], 'Service-Selection' = [Apn]} = Req, - Result = aaa_diameter_swx:server_assignment_request(UserName, 1, Apn), + Result = aaa_diameter_swm:get_ue_fsm_by_imsi(UserName), case Result of - {ok, _} -> - ResultCode = 2001; - {error, _Err} -> - ResultCode = ?'RULE-FAILURE-CODE_CM_AUTHORIZATION_REJECTED' + {ok, Pid} -> + ok = aaa_ue_fsm:ev_rx_s6b_aar(Pid, Apn), + lager:debug("Waiting for S6b AAA~n", []), + receive + {aaa, ResultCode} -> lager:debug("Rx AAA with ResultCode=~p~n", [ResultCode]) + end; + _ -> lager:error("Error looking up FSM for IMSI~n", [UserName]), + ResultCode = ?'RULE-FAILURE-CODE_CM_AUTHORIZATION_REJECTED' end, - Resp = #'AAA'{'Session-Id'=SessionId, + Resp = #'AAA'{'Session-Id'= SessionId, 'Auth-Application-Id' = AuthAppId, 'Auth-Request-Type' = AuthReqType, 'Result-Code' = ResultCode, 'Origin-Host' = OH, 'Origin-Realm' = OR}, lager:info("S6b Tx to ~p: ~p~n", [Caps, Resp]), - {reply, Resp}; + {reply, Resp}; % 3GPP TS 29.273 9.2.2.3.1 Session-Termination-Request (STR) Command: handle_request(#diameter_packet{msg = Req, errors = []}, _SvcName, {_, Caps}) when is_record(Req, 'STR') -> diff --git a/src/aaa_diameter_swm.erl b/src/aaa_diameter_swm.erl index a3e5132..68aa054 100644 --- a/src/aaa_diameter_swm.erl +++ b/src/aaa_diameter_swm.erl @@ -7,14 +7,22 @@ -include_lib("diameter_3gpp_ts29_273_swx.hrl"). -record(swm_state, { - table_id % ets table id + table_id, % ets table id, + ues = sets:new() }). +-record(swm_session, { + imsi :: binary(), + pid :: pid() + }). + -export([start_link/0]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2]). -export([code_change/3, terminate/2]). +-export([get_ue_fsm_by_imsi/1]). -export([auth_request/1, auth_compl_request/2, session_termination_request/1]). +-export([auth_response/2, auth_compl_response/2]). -define(SERVER, ?MODULE). @@ -25,7 +33,21 @@ TableId = ets:new(auth_req, [bag, named_table]), {ok, #swm_state{table_id = TableId}}. +get_ue_fsm_by_imsi(Imsi) -> + _Result = gen_server:call(?SERVER, {get_ue_fsm_by_imsi, Imsi}). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Tx over emulated SWm wire: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +auth_response(Imsi, Result) -> + _Result = gen_server:call(?SERVER, {epdg_auth_resp, Imsi, Result}). + +auth_compl_response(Imsi, Result) -> + _Result = gen_server:call(?SERVER, {epdg_auth_compl_resp, Imsi, Result}). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Rx from emulated SWm wire: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% auth_request(Imsi) -> gen_server:cast(?SERVER, {epdg_auth_req, Imsi}). @@ -35,25 +57,18 @@ session_termination_request(Imsi) -> gen_server:cast(?SERVER, {str, Imsi}). -handle_cast({epdg_auth_req, Imsi}, State) -> - % request the diameter code for a tuple - CKey = [], - IntegrityKey = [], - Result = aaa_diameter_swx:multimedia_auth_request(Imsi, 1, "EAP-AKA", 1, CKey, IntegrityKey), - case Result of - {ok, _MAA} -> epdg_diameter_swm:auth_response(Imsi, Result); - {error, _Err} -> epdg_diameter_swm:auth_response(Imsi, Result); - _ -> epdg_diameter_swm:auth_response(Imsi, {error, unknown}) - end, - {noreply, State}; +handle_cast({epdg_auth_req, Imsi}, State0) -> + {Sess, State1} = find_or_new_swm_session(Imsi, State0), + aaa_ue_fsm:ev_swm_auth_req(Sess#swm_session.pid), + {noreply, State1}; handle_cast({epdg_auth_compl_req, Imsi, Apn}, State) -> - % request the diameter code for a tuple - Result = aaa_diameter_swx:server_assignment_request(Imsi, 1, Apn), - case Result of - {ok, _SAA} -> epdg_diameter_swm:auth_compl_response(Imsi, Result); - {error, _Err} -> epdg_diameter_swm:auth_compl_response(Imsi, Result); - _ -> epdg_diameter_swm:auth_compl_response(Imsi, {error, unknown}) + Sess = find_swm_session_by_imsi(Imsi, State), + case Sess of + #swm_session{imsi = Imsi} -> + aaa_ue_fsm:ev_swm_auth_compl(Sess#swm_session.pid, Apn); + undefined -> + epdg_diameter_swm:auth_compl_response(Imsi, {error, imsi_unknown}) end, {noreply, State}; @@ -69,6 +84,24 @@ error_logger:error_report(["unknown handle_info", {module, ?MODULE}, {info, Info}, {state, S}]), {noreply, S}. +handle_call({get_ue_fsm_by_imsi, Imsi}, _From, State) -> + Sess = find_swm_session_by_imsi(Imsi, State), + lager:debug("find_swm_session_by_imsi(~p) returned ~p~n", [Imsi, Sess]), + case Sess of + #swm_session{} -> + {reply, {ok ,Sess#swm_session.pid}, State}; + undefined -> + {reply, {error, imsi_unknown}, State} + end; + +handle_call({epdg_auth_resp, Imsi, Result}, _From, State) -> + epdg_diameter_swm:auth_response(Imsi, Result), + {reply, ok, State}; + +handle_call({epdg_auth_compl_resp, Imsi, Result}, _From, State) -> + epdg_diameter_swm:auth_compl_response(Imsi, Result), + {reply, ok, State}; + handle_call(Request, From, S) -> error_logger:error_report(["unknown handle_call", {module, ?MODULE}, {request, Request}, {from, From}, {state, S}]), {noreply, S}. @@ -81,3 +114,35 @@ terminate(Reason, _S) -> lager:info("terminating ~p with reason ~p~n", [?MODULE, Reason]). + +%% ------------------------------------------------------------------ +%% Internal Function Definitions +%% ------------------------------------------------------------------ + +new_swm_session(Imsi, State) -> + {ok, Pid} = aaa_ue_fsm:start_link(Imsi), + UE = #swm_session{imsi = Imsi, pid = Pid}, + NewSt = State#swm_state{ues = sets:add_element(UE, State#swm_state.ues)}, + {UE, NewSt}. + +% returns swm_session if found, undefined if not +find_swm_session_by_imsi(Imsi, State) -> + sets:fold( + fun(UEsIt = #swm_session{imsi = Imsi}, _AccIn) -> UEsIt; + (_, AccIn) -> AccIn + end, + undefined, + State#swm_state.ues). + +find_or_new_swm_session(Imsi, State) -> + UE = find_swm_session_by_imsi(Imsi, State), + case UE of + #swm_session{imsi = Imsi} -> + {UE, State}; + undefined -> + new_swm_session(Imsi, State) + end. + +delete_swm_session(Imsi, State) -> + SetRemoved = sets:del_element(Imsi, State#swm_state.ues), + State#swm_state{ues = SetRemoved}. \ No newline at end of file diff --git a/src/aaa_diameter_swx.erl b/src/aaa_diameter_swx.erl index 411c000..1db5809 100644 --- a/src/aaa_diameter_swx.erl +++ b/src/aaa_diameter_swx.erl @@ -181,7 +181,7 @@ parse_saa(Saa) -> {unknown_err, []}. -handle_call({mar, {IMSI, NumAuthItems, AuthScheme, RAT, CKey, IntegrityKey}}, _From, State) -> +handle_call({mar, {IMSI, NumAuthItems, AuthScheme, RAT, CKey, IntegrityKey}}, {Pid, _Tag} = _From, State) -> SessionId = diameter:session_id(application:get_env(?ENV_APP_NAME, origin_host, ?ENV_DEFAULT_ORIG_HOST)), MAR = #'MAR'{'Vendor-Specific-Application-Id' = #'Vendor-Specific-Application-Id'{ 'Vendor-Id' = ?VENDOR_ID_3GPP, @@ -196,20 +196,17 @@ 'SIP-Number-Auth-Items' = NumAuthItems, 'RAT-Type' = RAT }, - Ret = diameter:call(?SVC_NAME, ?APP_ALIAS, MAR, []), + Ret = diameter:call(?SVC_NAME, ?APP_ALIAS, MAR, [{extra, [Pid]}, detach]), case Ret of - {ok, MAA} -> - SuccessCode = parse_maa(MAA), - case SuccessCode of - {ok, _} -> {reply, {ok, MAA}, State}; - {Err, Info} -> {reply, {error, {Err, Info, MAA}}, State} - end; + ok -> + {reply, ok, State}; {error, Err} -> lager:error("Error: ~w~n", [Err]), {reply, {error, Err}, State} end; -handle_call({sar, {IMSI, Type, APN}}, _From, State) -> +handle_call({sar, {IMSI, Type, APN}}, {Pid, _Tag} = _From, State) -> + lager:debug("SWx Tx SAR Imsi=~p Type=~p APN=~p~n", [IMSI, Type, APN]), SessionId = diameter:session_id(application:get_env(?ENV_APP_NAME, origin_host, ?ENV_DEFAULT_ORIG_HOST)), SAR = #'SAR'{'Vendor-Specific-Application-Id' = #'Vendor-Specific-Application-Id'{ 'Vendor-Id' = ?VENDOR_ID_3GPP, @@ -220,14 +217,10 @@ 'Server-Assignment-Type' = Type, 'Service-Selection' = [APN] }, - Ret = diameter:call(?SVC_NAME, ?APP_ALIAS, SAR, []), + Ret = diameter:call(?SVC_NAME, ?APP_ALIAS, SAR, [{extra, [Pid]}, detach]), case Ret of - {ok, Saa} -> - SuccessCode = parse_saa(Saa), - case SuccessCode of - {ok, _} -> {reply, {ok, Saa}, State}; - {Err, Info} -> {reply, {error, {Err, Info, Saa}}, State} - end; + ok -> + {reply, ok, State}; {error, Err} -> lager:error("Error: ~w~n", [Err]), {reply, {error, Err}, State} diff --git a/src/aaa_diameter_swx_cb.erl b/src/aaa_diameter_swx_cb.erl index 215e051..a7b9b7c 100644 --- a/src/aaa_diameter_swx_cb.erl +++ b/src/aaa_diameter_swx_cb.erl @@ -7,13 +7,14 @@ -include_lib("diameter_3gpp_ts29_273_swx.hrl"). %% diameter callbacks --export([peer_up/3, peer_down/3, pick_peer/4, prepare_request/3, prepare_retransmit/3, - handle_answer/4, handle_error/4, handle_request/3]). +-export([peer_up/3, peer_down/3, pick_peer/4, pick_peer/5, prepare_request/3, prepare_request/4, + prepare_retransmit/3, prepare_retransmit/4, + handle_answer/4, handle_answer/5, handle_error/4, handle_request/3]). %% peer_up/3 peer_up(_SvcName, Peer, State) -> lager:info("Peer up: ~p~n", [Peer]), - State. + State. %% peer_down/3 peer_down(_SvcName, Peer, State) -> @@ -23,9 +24,10 @@ %% pick_peer/4 pick_peer([Peer | _], _, _SvcName, _State) -> {ok, Peer}. +pick_peer([Peer | _], _, _SvcName, _State, _ExtraPars) -> + {ok, Peer}. %% prepare_request/3 - prepare_request(#diameter_packet{msg = [ T | Avps ]}, _, {_, Caps}) when is_list(Avps) -> #diameter_caps{origin_host = {OH, DH}, origin_realm = {OR, DR}} = Caps, @@ -35,9 +37,9 @@ {'Origin-Realm', OR}, {'Destination-Host', [DH]}, {'Destination-Realm', DR} - | Avps]}; + | Avps]}. % TODO: is there a simple way to capture all the following requests? -prepare_request(#diameter_packet{msg = Req}, _, {_, Caps}) +prepare_request(#diameter_packet{msg = Req}, _, {_, Caps}, _ExtraPars) when is_record(Req, 'MAR') -> #diameter_caps{origin_host = {OH, DH}, origin_realm = {OR, DR}} = Caps, Msg = Req#'MAR'{'Origin-Host' = OH, @@ -45,36 +47,40 @@ 'Destination-Host' = [DH], 'Destination-Realm' = DR}, {send, Msg}; -prepare_request(#diameter_packet{msg = Req}, _, {_, Caps}) +%% prepare_request/4 +prepare_request(#diameter_packet{msg = Req}, _, {_, Caps}, _ExtraPars) when is_record(Req, 'SAR') -> #diameter_caps{origin_host = {OH, DH}, origin_realm = {OR, DR}} = Caps, Msg = Req#'SAR'{'Origin-Host' = OH, 'Origin-Realm' = OR, 'Destination-Host' = [DH], 'Destination-Realm' = DR}, + lager:debug("SWx prepare_request: ~p~n", [Msg]), {send, Msg}. %% prepare_retransmit/3 prepare_retransmit(Packet, SvcName, Peer) -> prepare_request(Packet, SvcName, Peer). +%% prepare_retransmit/4 +prepare_retransmit(Packet, SvcName, Peer, ExtraPars) -> + prepare_request(Packet, SvcName, Peer, ExtraPars). + %% handle_answer/4 - -%% Since client.erl has detached the call when using the list -%% encoding and not otherwise, output to the terminal in the -%% the former case, return in the latter. - -handle_answer(#diameter_packet{msg = Msg, errors = []}, Request, _SvcName, _Peer) - when is_list(Request) -> +handle_answer(#diameter_packet{msg = Msg, errors = Errors}, _Request, _SvcName, Peer, ReqPid) when is_record(Msg, 'MAA') -> + lager:info("SWx Rx MAA ~p: ~p/ Errors ~p ~n", [Peer, Msg, Errors]), + aaa_ue_fsm:ev_rx_swx_maa(ReqPid, Msg), {ok, Msg}; -handle_answer(#diameter_packet{msg = Msg, errors = Errors}, Request, _SvcName, _Peer) - when is_list(Request) -> - {error, Errors}; - -handle_answer(#diameter_packet{msg = Msg, errors = []}, _Request, _SvcName, _Peer) -> +handle_answer(#diameter_packet{msg = Msg, errors = Errors}, _Request, _SvcName, Peer, ReqPid) when is_record(Msg, 'SAA') -> + lager:info("SWx Rx SAA ~p: ~p/ Errors ~p ~n", [Peer, Msg, Errors]), + #'SAA'{'Result-Code' = [ResultCode]} = Msg, + aaa_ue_fsm:ev_rx_swx_saa(ReqPid, ResultCode), + {ok, Msg}. +handle_answer(#diameter_packet{msg = Msg, errors = []}, _Request, _SvcName, Peer) -> + lager:info("SWx Rx ~p: ~p~n", [Peer, Msg]), {ok, Msg}; -handle_answer(#diameter_packet{msg = Msg, errors = Errors}, _Request, _SvcName, _Peer) -> - lager:info("Some Answer res: ~p / Errors ~p ~n", [Msg, Errors]), +handle_answer(#diameter_packet{msg = Msg, errors = Errors}, _Request, _SvcName, Peer) -> + lager:info("SWx Rx ~p: ~p / Errors ~p ~n", [Peer, Msg, Errors]), {error, Errors}. %% handle_error/4 diff --git a/src/aaa_ue_fsm.erl b/src/aaa_ue_fsm.erl new file mode 100644 index 0000000..e214540 --- /dev/null +++ b/src/aaa_ue_fsm.erl @@ -0,0 +1,185 @@ +% UE FSM +% (C) 2023 by sysmocom +% +% All Rights Reserved +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU Affero General Public License as +% published by the Free Software Foundation; either version 3 of the +% License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU Affero General Public License +% along with this program. If not, see <http://www.gnu.org/licenses/>. +% +% Additional Permission under GNU AGPL version 3 section 7: +% +% If you modify this Program, or any covered work, by linking or +% combining it with runtime libraries of Erlang/OTP as released by +% Ericsson on http://www.erlang.org (or a modified version of these +% libraries), containing parts covered by the terms of the Erlang Public +% License (http://www.erlang.org/EPLICENSE), the licensors of this +% Program grant you additional permission to convey the resulting work +% without the need to license the runtime libraries of Erlang/OTP under +% the GNU Affero General Public License. Corresponding Source for a +% non-source form of such a combination shall include the source code +% for the parts of the runtime libraries of Erlang/OTP used as well as +% that of the covered work. + +-module(aaa_ue_fsm). +-behaviour(gen_statem). +-define(NAME, aaa_ue_fsm). + +-include_lib("diameter/include/diameter.hrl"). +-include_lib("diameter_3gpp_ts29_273_s6b.hrl"). + +-export([start_link/1]). +-export([init/1,callback_mode/0,terminate/3]). +-export([ev_swm_auth_req/1, ev_swm_auth_compl/2, ev_rx_swx_maa/2, ev_rx_swx_saa/2, ev_rx_s6b_aar/2]). +-export([state_new/3, state_wait_swx_maa/3, state_wait_swx_saa/3, state_authenticated/3, state_authenticated_wait_swx_saa/3]). + +-record(ue_fsm_data, { + imsi = unknown :: binary(), + epdg_sess_active = false :: boolean(), + pgw_sess_active = false :: boolean(), + s6b_resp_pid :: pid() + }). + +start_link(Imsi) -> + ServerName = lists:concat([?NAME, "_", binary_to_list(Imsi)]), + lager:info("ue_fsm start_link(~p)~n", [ServerName]), + gen_statem:start_link({local, list_to_atom(ServerName)}, ?MODULE, Imsi, [{debug, [trace]}]). + +ev_swm_auth_req(Pid) -> + lager:info("ue_fsm ev_swm_auth_req~n", []), + try + gen_statem:call(Pid, swm_auth_req) + catch + exit:Err -> + {error, Err} + end. + +ev_swm_auth_compl(Pid, Apn) -> + lager:info("ue_fsm ev_swm_auth_compl~n", []), + try + gen_statem:call(Pid, {swm_auth_compl, Apn}) + catch + exit:Err -> + {error, Err} + end. + +ev_rx_swx_maa(Pid, MAA) -> + lager:info("ue_fsm ev_rx_swx_maa~n", []), + try + gen_statem:call(Pid, {rx_swx_maa, MAA}) + catch + exit:Err -> + {error, Err} + end. + +ev_rx_swx_saa(Pid, ResultCode) -> + lager:info("ue_fsm ev_rx_swx_saa~n", []), + try + gen_statem:call(Pid, {rx_swx_saa, ResultCode}) + catch + exit:Err -> + {error, Err} + end. + +ev_rx_s6b_aar(Pid, Apn) -> + lager:info("ue_fsm ev_rx_s6b_aar: ~p~n", [Apn]), + try + gen_statem:call(Pid, {rx_s6b_aar, Apn}) + catch + exit:Err -> + {error, Err} + end. + +%% ------------------------------------------------------------------ +%% Internal helpers +%% ------------------------------------------------------------------ + +%% ------------------------------------------------------------------ +%% gen_statem Function Definitions +%% ------------------------------------------------------------------ + +init(Imsi) -> + lager:info("ue_fsm init(~p)~n", [Imsi]), + Data = #ue_fsm_data{imsi = Imsi}, + {ok, state_new, Data}. + +callback_mode() -> + [state_functions, state_enter]. + +terminate(Reason, State, Data) -> + lager:info("terminating ~p with reason ~p state=~p, ~p~n", [?MODULE, Reason, State, Data]), + ok. + +state_new(enter, _OldState, Data) -> + {keep_state, Data}; + +state_new({call, From}, swm_auth_req, Data) -> + lager:info("ue_fsm state_new event=swm_auth_req, ~p~n", [Data]), + % request the diameter code for a tuple + CKey = [], + IntegrityKey = [], + case aaa_diameter_swx:multimedia_auth_request(Data#ue_fsm_data.imsi, 1, "EAP-AKA", 1, CKey, IntegrityKey) of + ok -> {next_state, state_wait_swx_maa, Data, [{reply,From,ok}]}; + {error, Err} -> {keep_state, Data, [{reply,From,{error, Err}}]} + end; + +state_new({call, From}, {swm_auth_compl, Apn}, Data) -> + lager:info("ue_fsm state_new event=swm_auth_compl, ~p~n", [Data]), + case aaa_diameter_swx:server_assignment_request(Data#ue_fsm_data.imsi, 1, Apn) of + ok -> {next_state, state_wait_swx_saa, Data, [{reply,From,ok}]}; + {error, Err} -> {keep_state, Data, [{reply,From,{error, Err}}]} + end. + +state_wait_swx_maa(enter, _OldState, Data) -> + {keep_state, Data}; + +state_wait_swx_maa({call, From}, {rx_swx_maa, MAA}, Data) -> + lager:info("ue_fsm state_wait_swx_maa event=rx_swx_maa, ~p~n", [Data]), + aaa_diameter_swm:auth_response(Data#ue_fsm_data.imsi, {ok, MAA}), + % TODO: don't transit if SAS returned error code. + {next_state, state_new, Data, [{reply,From,ok}]}. + +state_wait_swx_saa(enter, _OldState, Data) -> + {keep_state, Data}; + +state_wait_swx_saa({call, From}, {rx_swx_saa, SAA}, Data) -> + lager:info("ue_fsm state_wait_swx_saa event=rx_swx_saa, ~p~n", [Data]), + aaa_diameter_swm:auth_compl_response(Data#ue_fsm_data.imsi, {ok, SAA}), + % TODO: don't transit if SAS returned error code. + {next_state, state_authenticated, Data, [{reply,From,ok}]}. + +state_authenticated(enter, _OldState, Data) -> + % Mark ePDG session as active: + Data1 = Data#ue_fsm_data{epdg_sess_active = true}, + {keep_state, Data1}; + +state_authenticated({call, {Pid, _Tag} = From}, {rx_s6b_aar, Apn}, Data) -> + lager:info("ue_fsm state_authenticated event=rx_s6b_aar Apn=~p, ~p~n", [Apn, Data]), + case aaa_diameter_swx:server_assignment_request(Data#ue_fsm_data.imsi, 1, Apn) of + ok -> Data1 = Data#ue_fsm_data{s6b_resp_pid = Pid}, + {next_state, state_authenticated_wait_swx_saa, Data1, [{reply,From,ok}]}; + {error, Err} -> {keep_state, Data, [{reply,From,{error, Err}}]} + end; + +state_authenticated({call, From}, _Whatever, Data) -> + lager:info("ue_fsm state_authenticated event=purge_ms_request, ~p~n", [Data]), + {keep_state, Data, [{reply,From,ok}]}. + +state_authenticated_wait_swx_saa(enter, _OldState, Data) -> + {keep_state, Data}; + +state_authenticated_wait_swx_saa({call, From}, {rx_swx_saa, ResultCode}, Data) -> + lager:info("ue_fsm state_authenticated_wait_swx_saa event=rx_swx_saa ResulCode=~p, ~p~n", [ResultCode, Data]), + aaa_diameter_s6b:tx_aa_answer(Data#ue_fsm_data.s6b_resp_pid, ResultCode), + Data1 = Data#ue_fsm_data{s6b_resp_pid = undefined}, + {next_state, state_authenticated, Data1, [{reply,From,ok}]}. + -- To view, visit https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35759?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: erlang/osmo-epdg Gerrit-Branch: master Gerrit-Change-Id: I78ebda4679d0a2f3ecede94598e74b20c2ff8836 Gerrit-Change-Number: 35759 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pes...@sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <lafo...@osmocom.org> Gerrit-Reviewer: lynxis lazus <lyn...@fe80.eu> Gerrit-Reviewer: pespin <pes...@sysmocom.de> Gerrit-MessageType: merged