Compare commits
6 Commits
74fff9f574
...
859807eb7f
Author | SHA1 | Date |
---|---|---|
Pau Espin | 859807eb7f | |
Pau Espin | 0d09d1e568 | |
Pau Espin | 56fd123844 | |
Pau Espin | c5ba31465d | |
Pau Espin | 57e2eb47a9 | |
Pau Espin | bc53ecd5ad |
|
@ -1,5 +1,5 @@
|
||||||
#!/bin/sh -ex
|
#!/bin/sh -ex
|
||||||
|
|
||||||
rebar3 compile
|
make clean || true
|
||||||
rebar3 escriptize
|
make
|
||||||
rebar3 eunit
|
make check
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
%
|
%
|
||||||
-hrl_name('conv.hrl').
|
-hrl_name('conv.hrl').
|
||||||
|
|
||||||
|
-define(VENDOR_ID_3GPP, 10415).
|
||||||
|
|
||||||
%% Can Hold information about Result-Code or Experimental-Result:
|
%% Can Hold information about Result-Code or Experimental-Result:
|
||||||
-record(epdg_dia_rc, {
|
-record(epdg_dia_rc, {
|
||||||
vendor_id :: non_neg_integer(), %% or undefined if Result-Code
|
vendor_id :: non_neg_integer(), %% or undefined if Result-Code
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
{osmo_gsup, {git, "https://gerrit.osmocom.org/erlang/osmo_gsup", {branch, "osmocom/epdg"}}}
|
{osmo_gsup, {git, "https://gerrit.osmocom.org/erlang/osmo_gsup", {branch, "osmocom/epdg"}}}
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
{minimum_otp_vsn, "20.3"}.
|
{minimum_otp_vsn, "25.2.3"}.
|
||||||
{plugins, [
|
{plugins, [
|
||||||
{rebar3_diameter_compiler,
|
{rebar3_diameter_compiler,
|
||||||
{git, "https://github.com/carlosedp/rebar3_diameter_compiler.git", {tag, "0.8.0"}}}
|
{git, "https://github.com/carlosedp/rebar3_diameter_compiler.git", {tag, "0.8.0"}}}
|
||||||
|
|
|
@ -47,12 +47,9 @@
|
||||||
-export([start_link/0]).
|
-export([start_link/0]).
|
||||||
-export([start/0, stop/0, terminate/2]).
|
-export([start/0, stop/0, terminate/2]).
|
||||||
%% gen_server Function Exports
|
%% gen_server Function Exports
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, peer_down/3]).
|
||||||
-export([code_change/3]).
|
-export([code_change/3]).
|
||||||
-export([multimedia_auth_request/6]).
|
|
||||||
-export([server_assignment_request/3]).
|
|
||||||
-export([tx_aa_answer/2, tx_st_answer/2]).
|
-export([tx_aa_answer/2, tx_st_answer/2]).
|
||||||
-export([test/0, test/1]).
|
|
||||||
|
|
||||||
%% Diameter Application Definitions
|
%% Diameter Application Definitions
|
||||||
-define(SERVER, ?MODULE).
|
-define(SERVER, ?MODULE).
|
||||||
|
@ -96,11 +93,6 @@
|
||||||
{module, ?CALLBACK_MOD},
|
{module, ?CALLBACK_MOD},
|
||||||
{answer_errors, callback}]}]).
|
{answer_errors, callback}]}]).
|
||||||
|
|
||||||
-record(state, {
|
|
||||||
handlers,
|
|
||||||
peers = #{}
|
|
||||||
}).
|
|
||||||
|
|
||||||
%% @doc starts gen_server implementation process
|
%% @doc starts gen_server implementation process
|
||||||
-spec start() -> ok | {error, term()}.
|
-spec start() -> ok | {error, term()}.
|
||||||
start() ->
|
start() ->
|
||||||
|
@ -115,9 +107,7 @@ stop() ->
|
||||||
start_link() ->
|
start_link() ->
|
||||||
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
|
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
|
||||||
|
|
||||||
peer_down(API, SvcName, {PeerRef, _} = Peer) ->
|
peer_down(_API, SvcName, {_PeerRef, _} = Peer) ->
|
||||||
% fixme: why do we still have ets here?
|
|
||||||
(catch ets:delete(?MODULE, {API, PeerRef})),
|
|
||||||
gen_server:cast(?SERVER, {peer_down, SvcName, Peer}),
|
gen_server:cast(?SERVER, {peer_down, SvcName, Peer}),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
@ -133,20 +123,6 @@ init(State) ->
|
||||||
{ok, _} = listen({address, Proto, Ip, Port}, {timer, ConnectTimer, WatchdogTimer, WatchdogConfig}),
|
{ok, _} = listen({address, Proto, Ip, Port}, {timer, ConnectTimer, WatchdogTimer, WatchdogConfig}),
|
||||||
{ok, State}.
|
{ok, State}.
|
||||||
|
|
||||||
test() ->
|
|
||||||
test("001011234567890").
|
|
||||||
|
|
||||||
test(IMSI) ->
|
|
||||||
multimedia_auth_request(IMSI, 3, "EAP-AKA", 1, [], []).
|
|
||||||
|
|
||||||
multimedia_auth_request(IMSI, NumAuthItems, AuthScheme, RAT, CKey, IntegrityKey) ->
|
|
||||||
gen_server:call(?SERVER,
|
|
||||||
{mar, {IMSI, NumAuthItems, AuthScheme, RAT, CKey, IntegrityKey}}).
|
|
||||||
% APN is optional and should be []
|
|
||||||
server_assignment_request(IMSI, Type, APN) ->
|
|
||||||
gen_server:call(?SERVER,
|
|
||||||
{sar, {IMSI, Type, APN}}).
|
|
||||||
|
|
||||||
tx_aa_answer(Pid, DiaRC) ->
|
tx_aa_answer(Pid, DiaRC) ->
|
||||||
% handle_request(AAR) was spawned into its own process, and it's blocked waiting for AAA:
|
% handle_request(AAR) was spawned into its own process, and it's blocked waiting for AAA:
|
||||||
Pid ! {aaa, DiaRC}.
|
Pid ! {aaa, DiaRC}.
|
||||||
|
@ -155,12 +131,8 @@ tx_st_answer(Pid, DiaRC) ->
|
||||||
% handle_request(STR) was spawned into its own process, and it's blocked waiting for STA:
|
% handle_request(STR) was spawned into its own process, and it's blocked waiting for STA:
|
||||||
Pid ! {sta, DiaRC}.
|
Pid ! {sta, DiaRC}.
|
||||||
|
|
||||||
result_code_success(2001) -> ok;
|
handle_call(Info, _From, State) ->
|
||||||
result_code_success(2002) -> ok;
|
error_logger:error_report(["unknown handle_call", {module, ?MODULE}, {info, Info}, {state, State}]).
|
||||||
result_code_success(_) -> invalid_result_code.
|
|
||||||
|
|
||||||
handle_call({aar, {IMSI, Type, APN}}, _From, State) ->
|
|
||||||
SessionId = diameter:session_id(application:get_env(?ENV_APP_NAME, origin_host, ?ENV_DEFAULT_ORIG_HOST)).
|
|
||||||
|
|
||||||
%% @callback gen_server
|
%% @callback gen_server
|
||||||
handle_cast(stop, State) ->
|
handle_cast(stop, State) ->
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
%% diameter callbacks
|
%% diameter callbacks
|
||||||
-export([peer_up/3, peer_down/3, pick_peer/4, pick_peer/5, prepare_request/3, prepare_request/4,
|
-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,
|
prepare_retransmit/3, prepare_retransmit/4,
|
||||||
handle_answer/4, handle_answer/5, handle_error/4, handle_error/5, handle_request/3]).
|
handle_request/3,
|
||||||
|
handle_answer/4, handle_answer/5, handle_error/4, handle_error/5]).
|
||||||
|
|
||||||
%% peer_up/3
|
%% peer_up/3
|
||||||
peer_up(_SvcName, Peer, State) ->
|
peer_up(_SvcName, Peer, State) ->
|
||||||
|
@ -67,6 +68,41 @@ prepare_retransmit(Packet, SvcName, Peer) ->
|
||||||
prepare_retransmit(Packet, SvcName, Peer, ExtraPars) ->
|
prepare_retransmit(Packet, SvcName, Peer, ExtraPars) ->
|
||||||
prepare_request(Packet, SvcName, Peer, ExtraPars).
|
prepare_request(Packet, SvcName, Peer, ExtraPars).
|
||||||
|
|
||||||
|
%% handle_request/3
|
||||||
|
|
||||||
|
%% 3GPP TS 29.273 8.2.2.4 Network Initiated De-Registration by HSS Procedure
|
||||||
|
handle_request(#diameter_packet{msg = Req, errors = []}, _SvcName, {_, Caps}) when is_record(Req, 'RTR') ->
|
||||||
|
lager:info("SWx Rx RTR from ~p: ~p~n", [Caps, Req]),
|
||||||
|
#diameter_caps{origin_host = {OH,_}, origin_realm = {OR,_}} = Caps,
|
||||||
|
#'RTR'{'Session-Id' = SessionId,
|
||||||
|
'Vendor-Specific-Application-Id' = VendorAppId,
|
||||||
|
'Auth-Session-State' = AuthSessState,
|
||||||
|
'User-Name' = Imsi,
|
||||||
|
'Deregistration-Reason' = _DeregReason} = Req,
|
||||||
|
case aaa_ue_fsm:get_pid_by_imsi(Imsi) of
|
||||||
|
Pid when is_pid(Pid) ->
|
||||||
|
aaa_ue_fsm:stop(Pid),
|
||||||
|
Res = 2001, %% Success
|
||||||
|
ERes = [];
|
||||||
|
undefined ->
|
||||||
|
Res = [],
|
||||||
|
%% TS 29.229 6.2.2.1 DIAMETER_ERROR_USER_UNKNOWN
|
||||||
|
ERes = #'Experimental-Result'{'Vendor-Id' = ?VENDOR_ID_3GPP, 'Experimental-Result-Code' = 5001}
|
||||||
|
end,
|
||||||
|
Resp = #'RTA'{'Session-Id' = SessionId,
|
||||||
|
'Vendor-Specific-Application-Id' = VendorAppId,
|
||||||
|
'Result-Code' = Res,
|
||||||
|
'Experimental-Result' = ERes,
|
||||||
|
'Auth-Session-State' = AuthSessState,
|
||||||
|
'Origin-Host' = OH,
|
||||||
|
'Origin-Realm' = OR},
|
||||||
|
lager:info("SWx Tx to ~p: ~p~n", [Caps, Resp]),
|
||||||
|
{reply, Resp};
|
||||||
|
|
||||||
|
handle_request(Msg, _SvcName, Peer) ->
|
||||||
|
lager:error("SWx Rx unexpected msg from ~p: ~p~n", [Peer, Msg]),
|
||||||
|
erlang:error({unexpected, ?MODULE, ?LINE}).
|
||||||
|
|
||||||
%% handle_answer/4
|
%% handle_answer/4
|
||||||
handle_answer(#diameter_packet{msg = Msg, errors = Errors}, _Request, _SvcName, Peer, ReqPid) when is_record(Msg, 'MAA') ->
|
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]),
|
lager:info("SWx Rx MAA ~p: ~p/ Errors ~p ~n", [Peer, Msg, Errors]),
|
||||||
|
@ -82,6 +118,7 @@ handle_answer(#diameter_packet{msg = Msg, errors = Errors}, _Request, _SvcName,
|
||||||
aaa_ue_fsm:ev_rx_swx_maa(ReqPid, {error, DiaRC})
|
aaa_ue_fsm:ev_rx_swx_maa(ReqPid, {error, DiaRC})
|
||||||
end,
|
end,
|
||||||
{ok, Msg};
|
{ok, Msg};
|
||||||
|
|
||||||
handle_answer(#diameter_packet{msg = Msg, errors = Errors}, Request, _SvcName, Peer, ReqPid) when is_record(Msg, 'SAA') ->
|
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]),
|
lager:info("SWx Rx SAA ~p: ~p/ Errors ~p ~n", [Peer, Msg, Errors]),
|
||||||
% Recover fields from originating request:
|
% Recover fields from originating request:
|
||||||
|
@ -103,9 +140,11 @@ handle_answer(#diameter_packet{msg = Msg, errors = Errors}, Request, _SvcName, P
|
||||||
aaa_ue_fsm:ev_rx_swx_saa(ReqPid, {error, SAType, DiaRC})
|
aaa_ue_fsm:ev_rx_swx_saa(ReqPid, {error, SAType, DiaRC})
|
||||||
end,
|
end,
|
||||||
{ok, Msg}.
|
{ok, Msg}.
|
||||||
|
|
||||||
handle_answer(#diameter_packet{msg = Msg, errors = []}, _Request, _SvcName, Peer) ->
|
handle_answer(#diameter_packet{msg = Msg, errors = []}, _Request, _SvcName, Peer) ->
|
||||||
lager:info("SWx Rx ~p: ~p~n", [Peer, Msg]),
|
lager:info("SWx Rx ~p: ~p~n", [Peer, Msg]),
|
||||||
{ok, Msg};
|
{ok, Msg};
|
||||||
|
|
||||||
handle_answer(#diameter_packet{msg = Msg, errors = Errors}, _Request, _SvcName, Peer) ->
|
handle_answer(#diameter_packet{msg = Msg, errors = Errors}, _Request, _SvcName, Peer) ->
|
||||||
lager:info("SWx Rx ~p: ~p / Errors ~p ~n", [Peer, Msg, Errors]),
|
lager:info("SWx Rx ~p: ~p / Errors ~p ~n", [Peer, Msg, Errors]),
|
||||||
{error, Errors}.
|
{error, Errors}.
|
||||||
|
@ -122,10 +161,6 @@ handle_error(Reason, _Request, _SvcName, _Peer, ExtraPars) ->
|
||||||
lager:error("SWx error: ~p, ExtraPars: ~p~n", [Reason, ExtraPars]),
|
lager:error("SWx error: ~p, ExtraPars: ~p~n", [Reason, ExtraPars]),
|
||||||
{error, Reason}.
|
{error, Reason}.
|
||||||
|
|
||||||
%% handle_request/3
|
|
||||||
handle_request(_Packet, _SvcName, _Peer) ->
|
|
||||||
erlang:error({unexpected, ?MODULE, ?LINE}).
|
|
||||||
|
|
||||||
%% ------------------------------------------------------------------
|
%% ------------------------------------------------------------------
|
||||||
%% Internal Function Definitions
|
%% Internal Function Definitions
|
||||||
%% ------------------------------------------------------------------
|
%% ------------------------------------------------------------------
|
||||||
|
|
|
@ -179,7 +179,7 @@ received_gtpc_delete_bearer_request(Pid) ->
|
||||||
ev_handle({call, From}, {auth_request, PdpTypeNr, Apn, EAP}, Data) ->
|
ev_handle({call, From}, {auth_request, PdpTypeNr, Apn, EAP}, Data) ->
|
||||||
case epdg_diameter_swm:auth_request(Data#ue_fsm_data.imsi, PdpTypeNr, Apn, EAP) of
|
case epdg_diameter_swm:auth_request(Data#ue_fsm_data.imsi, PdpTypeNr, Apn, EAP) of
|
||||||
ok -> {next_state, state_wait_auth_resp, Data, [{reply,From,ok}]};
|
ok -> {next_state, state_wait_auth_resp, Data, [{reply,From,ok}]};
|
||||||
{error, Err} -> {stop_and_reply, Err, Data, [{reply,From,{error,Err}}]}
|
{error, Err} -> {stop_and_reply, Err, [{reply,From,{error,Err}}], Data}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% ------------------------------------------------------------------
|
%% ------------------------------------------------------------------
|
||||||
|
@ -211,7 +211,7 @@ state_new({call, _From} = EvType, {auth_request, PdpTypeNr, Apn, EAP} = EvConten
|
||||||
|
|
||||||
state_new({call, From}, purge_ms_request, Data) ->
|
state_new({call, From}, purge_ms_request, Data) ->
|
||||||
lager:info("ue_fsm state_new event=purge_ms_request, ~p~n", [Data]),
|
lager:info("ue_fsm state_new event=purge_ms_request, ~p~n", [Data]),
|
||||||
{stop_and_reply, purge_ms_request, Data, [{reply,From,ok}]}.
|
{stop_and_reply, purge_ms_request, [{reply,From,ok}], Data}.
|
||||||
|
|
||||||
state_wait_auth_resp(enter, _OldState, Data) ->
|
state_wait_auth_resp(enter, _OldState, Data) ->
|
||||||
{keep_state, Data};
|
{keep_state, Data};
|
||||||
|
@ -242,7 +242,7 @@ state_authenticating({call, From}, lu_request, Data) ->
|
||||||
% Rx "GSUP CEAI LU Req" is our way of saying Rx "Swm Diameter-EAP REQ (DER) with EAP AVP containing successuful auth":
|
% Rx "GSUP CEAI LU Req" is our way of saying Rx "Swm Diameter-EAP REQ (DER) with EAP AVP containing successuful auth":
|
||||||
case epdg_diameter_swm:auth_compl_request(Data#ue_fsm_data.imsi, Data#ue_fsm_data.apn) of
|
case epdg_diameter_swm:auth_compl_request(Data#ue_fsm_data.imsi, Data#ue_fsm_data.apn) of
|
||||||
ok -> {keep_state, Data, [{reply,From,ok}]};
|
ok -> {keep_state, Data, [{reply,From,ok}]};
|
||||||
{error, Err} -> {stop_and_reply, Err, Data, [{reply,From,{error,Err}}]}
|
{error, Err} -> {stop_and_reply, Err, [{reply,From,{error,Err}}], Data}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
% Rx Swm Diameter-EAP Answer (DEA) containing APN-Configuration, triggered by
|
% Rx Swm Diameter-EAP Answer (DEA) containing APN-Configuration, triggered by
|
||||||
|
|
|
@ -260,7 +260,7 @@ purge_ms_response(Imsi, Result) ->
|
||||||
|
|
||||||
% Our GSUP CEAI implementation for "IKEv2 Information Delete Request"
|
% Our GSUP CEAI implementation for "IKEv2 Information Delete Request"
|
||||||
cancel_location_request(Imsi) ->
|
cancel_location_request(Imsi) ->
|
||||||
lager:info("cancel_location_request(~p): ~p~n", [Imsi]),
|
lager:info("cancel_location_request(~p)~n", [Imsi]),
|
||||||
gen_server:cast(?SERVER, {cancel_location_request, Imsi}).
|
gen_server:cast(?SERVER, {cancel_location_request, Imsi}).
|
||||||
|
|
||||||
%% ------------------------------------------------------------------
|
%% ------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue