pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/36180?usp=email )
Change subject: Forward failure SWx MAA -> GSUP AuthInfo Error ......................................................................
Forward failure SWx MAA -> GSUP AuthInfo Error
Change-Id: I48066058e601a4ca4d46e239f7a7060bbc20a32b --- M include/conv.hrl M src/aaa_diameter_swx_cb.erl M src/aaa_ue_fsm.erl M src/conv.erl M src/epdg_ue_fsm.erl M src/gsup_server.erl 6 files changed, 100 insertions(+), 32 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-epdg refs/changes/80/36180/1
diff --git a/include/conv.hrl b/include/conv.hrl index 80b7e5b..786bdff 100644 --- a/include/conv.hrl +++ b/include/conv.hrl @@ -31,6 +31,12 @@ % -hrl_name('conv.hrl').
+%% Can Hold information about Result-Code or Experimental-Result: +-record(epdg_dia_rc, { + vendor_id :: non_neg_integer(), %% or undefined if Result-Code + result_code :: non_neg_integer() +}). + -record(epdg_eua, { type_nr :: non_neg_integer(), ipv4 :: binary(), diff --git a/src/aaa_diameter_swx_cb.erl b/src/aaa_diameter_swx_cb.erl index 0457259..8a6dd08 100644 --- a/src/aaa_diameter_swx_cb.erl +++ b/src/aaa_diameter_swx_cb.erl @@ -70,18 +70,27 @@ %% handle_answer/4 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]), - #'MAA'{'SIP-Auth-Data-Item' = SipAuthTuples} = Msg, - AuthTuples = lists:map(fun dia_sip2epdg_auth_tuple/1, SipAuthTuples), - % TODO: handle error case.... - aaa_ue_fsm:ev_rx_swx_maa(ReqPid, {ok, AuthTuples}), + #'MAA'{'Result-Code' = ResultCodeOpt, + 'Experimental-Result' = ExperimentalResultOpt} = Msg, + DiaRC = parse_epdg_dia_rc(ResultCodeOpt, ExperimentalResultOpt), + case dia_rc_success(DiaRC) of + ok -> + #'MAA'{'SIP-Auth-Data-Item' = SipAuthTuples} = Msg, + AuthTuples = lists:map(fun dia_sip2epdg_auth_tuple/1, SipAuthTuples), + aaa_ue_fsm:ev_rx_swx_maa(ReqPid, {ok, AuthTuples}); + _ -> + aaa_ue_fsm:ev_rx_swx_maa(ReqPid, {error, DiaRC}) + end, {ok, Msg}; 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]), % Recover fields from originating request: #'SAR'{'Server-Assignment-Type' = SAType} = Request, % Retrieve fields from answer: - #'SAA'{'Result-Code' = [ResultCode]} = Msg, - case result_code_success(ResultCode) of + #'SAA'{'Result-Code' = ResultCodeOpt, + 'Experimental-Result' = ExperimentalResultOpt} = Msg, + DiaRC = parse_epdg_dia_rc(ResultCodeOpt, ExperimentalResultOpt), + case dia_rc_success(DiaRC) of ok -> #'SAA'{'Non-3GPP-User-Data' = N3UA} = Msg, PGWAddresses = parse_pgw_addr_from_N3UA(N3UA), @@ -91,7 +100,7 @@ end, aaa_ue_fsm:ev_rx_swx_saa(ReqPid, {ok, SAType, ResInfo}); _ -> - aaa_ue_fsm:ev_rx_swx_saa(ReqPid, {error, SAType, ResultCode}) + aaa_ue_fsm:ev_rx_swx_saa(ReqPid, {error, SAType, DiaRC}) end, {ok, Msg}. handle_answer(#diameter_packet{msg = Msg, errors = []}, _Request, _SvcName, Peer) -> @@ -121,9 +130,19 @@ %% Internal Function Definitions %% ------------------------------------------------------------------
-result_code_success(2001) -> ok; -result_code_success(2002) -> ok; -result_code_success(_) -> invalid_result_code. +dia_rc_success(#epdg_dia_rc{result_code = 2001}) -> ok; +dia_rc_success(#epdg_dia_rc{result_code = 2002}) -> ok; +dia_rc_success(_) -> invalid_result_code. + +parse_epdg_dia_rc([], []) -> + #epdg_dia_rc{vendor_id = undefined, result_code = 2001 }; +parse_epdg_dia_rc([ResultCode], []) -> + #epdg_dia_rc{vendor_id = undefined, result_code = ResultCode }; +parse_epdg_dia_rc([], [ExpResultCode]) -> + #'Experimental-Result'{'Vendor-Id' = VendorId, 'Experimental-Result-Code' = ERC} = ExpResultCode, + #epdg_dia_rc{vendor_id = VendorId, result_code = ERC }; +parse_epdg_dia_rc([ResultCode], [_ExpResultCode]) -> + parse_epdg_dia_rc([ResultCode], []).
dia_sip2epdg_auth_tuple(#'SIP-Auth-Data-Item'{'SIP-Authenticate' = [Authenticate], 'SIP-Authorization' = [Authorization], diff --git a/src/aaa_ue_fsm.erl b/src/aaa_ue_fsm.erl index 9e41756..55eea36 100644 --- a/src/aaa_ue_fsm.erl +++ b/src/aaa_ue_fsm.erl @@ -175,7 +175,6 @@ state_wait_swx_maa({call, From}, {rx_swx_maa, Result}, 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, Result), - % TODO: don't transit if SAS returned error code. {next_state, state_new, Data, [{reply,From,ok}]}.
state_wait_swx_saa(enter, _OldState, Data) -> diff --git a/src/conv.erl b/src/conv.erl index cdba445..1a15a3c 100644 --- a/src/conv.erl +++ b/src/conv.erl @@ -40,6 +40,7 @@
-export([ip_to_bin/1, bin_to_ip/1]). -export([cause_gtp2gsup/1]). +-export([dia_rc_to_gsup_cause/1]). -export([gtp2_paa_to_epdg_eua/1, epdg_eua_to_gsup_pdp_address/1]). -export([nai_to_imsi/1]).
@@ -76,6 +77,32 @@ cause_gtp2gsup(_) -> ?GSUP_CAUSE_PROTO_ERR_UNSPEC.
+-define(DIA_VENDOR_3GPP, 10415). +% transient (only in Experimental-Result-Code) +-define(DIAMETER_AUTHENTICATION_DATA_UNAVAILABLE, 4181). +-define(DIAMETER_ERROR_CAMEL_SUBSCRIPTION_PRESENT, 4182). +% permanent (only in Experimental-Result-Code) +-define(DIAMETER_ERROR_USER_UNKNOWN, 5001). +-define(DIAMETER_AUTHORIZATION_REJECTED, 5003). +-define(DIAMETER_ERROR_ROAMING_NOT_ALLOWED, 5004). +-define(DIAMETER_MISSING_AVP, 5005). +-define(DIAMETER_UNABLE_TO_COMPLY, 5012). +-define(DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION, 5420). +-define(DIAMETER_ERROR_RAT_NOT_ALLOWED, 5421). +-define(DIAMETER_ERROR_EQUIPMENT_UNKNOWN, 5422). +-define(DIAMETER_ERROR_UNKOWN_SERVING_NODE, 5423). + +-spec dia_rc_to_gsup_cause(#epdg_dia_rc{}) -> non_neg_integer(). +dia_rc_to_gsup_cause(#epdg_dia_rc{result_code = 2001}) -> 0; +dia_rc_to_gsup_cause(#epdg_dia_rc{result_code = 2002}) -> 0; +dia_rc_to_gsup_cause(#epdg_dia_rc{result_code = ?DIAMETER_ERROR_USER_UNKNOWN}) -> ?GSUP_CAUSE_IMSI_UNKNOWN; +dia_rc_to_gsup_cause(#epdg_dia_rc{result_code = ?DIAMETER_AUTHORIZATION_REJECTED}) -> ?GSUP_CAUSE_LA_NOTALLOWED; +dia_rc_to_gsup_cause(#epdg_dia_rc{result_code = ?DIAMETER_ERROR_ROAMING_NOT_ALLOWED}) -> ?GSUP_CAUSE_ROAMING_NOTALLOWED; +dia_rc_to_gsup_cause(#epdg_dia_rc{result_code = ?DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION}) -> ?GSUP_CAUSE_NO_SUIT_CELL_IN_LA; +dia_rc_to_gsup_cause(#epdg_dia_rc{result_code = ?DIAMETER_UNABLE_TO_COMPLY}) -> ?GSUP_CAUSE_NET_FAIL; +dia_rc_to_gsup_cause(#epdg_dia_rc{result_code = ?DIAMETER_MISSING_AVP}) -> ?GSUP_CAUSE_PROTO_ERR_UNSPEC; +dia_rc_to_gsup_cause(_) -> ?GSUP_CAUSE_NET_FAIL. + gtp2_paa_to_epdg_eua(#v2_pdn_address_allocation{type = ipv4, address = Addr}) -> #epdg_eua{type_nr = ?GTP_PDP_ADDR_TYPE_NR_IPv4, ipv4 = Addr}; diff --git a/src/epdg_ue_fsm.erl b/src/epdg_ue_fsm.erl index 703e242..1414190 100644 --- a/src/epdg_ue_fsm.erl +++ b/src/epdg_ue_fsm.erl @@ -218,12 +218,14 @@
state_wait_auth_resp({call, From}, {received_swm_auth_response, Result}, Data) -> lager:info("ue_fsm state_wait_auth_resp event=received_swm_auth_response Result=~p, ~p~n", [Result, Data]), - gsup_server:auth_response(Data#ue_fsm_data.imsi, Result), case Result of - {ok, _} -> + {ok, _AuthTuples} -> + gsup_server:auth_response(Data#ue_fsm_data.imsi, Result), {next_state, state_authenticating, Data, [{reply,From,ok}]}; - {error, Err} -> - {next_state, state_new, Data, [{reply,From,{error,Err}}]}; + {error, DiaRC} -> + GsupCause = conv:dia_rc_to_gsup_cause(DiaRC), + gsup_server:auth_response(Data#ue_fsm_data.imsi, {error, GsupCause}), + {next_state, state_new, Data, [{reply,From,ok}]}; _ -> {next_state, state_new, Data, [{reply,From,{error,unknown}}]} end. @@ -257,13 +259,12 @@ PGWAddrCandidateList -> Data1 = Data#ue_fsm_data{pgw_rem_addr_list = PGWAddrCandidateList} end, - Ret = ok, - gsup_server:lu_response(Data1#ue_fsm_data.imsi, Ret), - {next_state, state_authenticated, Data1, [{reply,From,Ret}]}; - {error, Err} -> - Ret = {error, Err}, - gsup_server:lu_response(Data#ue_fsm_data.imsi, Ret), - {next_state, state_new, Data, [{reply,From,Ret}]} + gsup_server:lu_response(Data1#ue_fsm_data.imsi, ok), + {next_state, state_authenticated, Data1, [{reply,From,ok}]}; + {error, DiaRC} -> + GsupCause = conv:dia_rc_to_gsup_cause(DiaRC), + gsup_server:lu_response(Data#ue_fsm_data.imsi, {error, GsupCause}), + {next_state, state_new, Data, [{reply,From,ok}]} end.
state_authenticated(enter, _OldState, Data) -> diff --git a/src/gsup_server.erl b/src/gsup_server.erl index d71836b..10495e1 100644 --- a/src/gsup_server.erl +++ b/src/gsup_server.erl @@ -122,7 +122,12 @@ imsi => Imsi, auth_tuples => lists:map(fun epdg_auth_tuple2gsup/1, AuthTuples) }; - {error, _} -> Resp = #{message_type => send_auth_info_err, imsi => Imsi, message_class => 5, cause => ?GSUP_CAUSE_NET_FAIL} + {error, Gsupcause} -> + Resp = #{message_type => send_auth_info_err, + imsi => Imsi, + message_class => 5, + cause => Gsupcause + } end, tx_gsup(Socket, Resp), {noreply, State}; @@ -131,15 +136,17 @@ lager:info("lu_response for ~p: ~p~n", [Imsi, Result]), Socket = State#gsups_state.socket, case Result of - ok -> Resp = #{message_type => location_upd_res, - imsi => Imsi, - message_class => 5 - }; - {error, _} -> Resp = #{message_type => location_upd_err, - imsi => Imsi, - message_class => 5, - cause => ?GSUP_CAUSE_NET_FAIL - } + ok -> + Resp = #{message_type => location_upd_res, + imsi => Imsi, + message_class => 5 + }; + {error, Gsupcause} -> + Resp = #{message_type => location_upd_err, + imsi => Imsi, + message_class => 5, + cause => Gsupcause + } end, tx_gsup(Socket, Resp), {noreply, State};