lists.osmocom.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
June
May
April
March
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
List overview
Download
gerrit-log
January 2024
----- 2025 -----
June 2025
May 2025
April 2025
March 2025
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
gerrit-log@lists.osmocom.org
1 participants
1559 discussions
Start a n
N
ew thread
[M] Change in pysim[master]: global_platform: Add shell command for PUT KEY
by laforge
laforge has uploaded this change for review. (
https://gerrit.osmocom.org/c/pysim/+/35684?usp=email
) Change subject: global_platform: Add shell command for PUT KEY ...................................................................... global_platform: Add shell command for PUT KEY This command is used for installation of GlobalPlatform keys. We only implement the command without secure messaging at this point, as it is used during card personalization. Authentication will later be handled by generic implementations of SCP02 and/or SCP03. Change-Id: Icffe9e7743266d7262fbf440dd361b21eed7c5cf --- M docs/shell.rst M pySim/global_platform.py 2 files changed, 65 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/84/35684/1 diff --git a/docs/shell.rst b/docs/shell.rst index 89a0d0a..8731cfe 100644 --- a/docs/shell.rst +++ b/docs/shell.rst @@ -947,6 +947,12 @@ :module: pySim.global_platform :func: ADF_SD.AddlShellCommands.store_data_parser +put_key +~~~~~~~ +.. argparse:: + :module: pySim.global_platform + :func: ADF_SD.AddlShellCommands.put_key_parser + eUICC ISD-R commands -------------------- diff --git a/pySim/global_platform.py b/pySim/global_platform.py index f7a4f64..fe6ffb3 100644 --- a/pySim/global_platform.py +++ b/pySim/global_platform.py @@ -446,7 +446,52 @@ response += data return data + put_key_parser = argparse.ArgumentParser() + put_key_parser.add_argument('--old-key-version-nr', type=auto_int, default=0, help='Old Key Version Number') + put_key_parser.add_argument('--key-version-nr', type=auto_int, required=True, help='Key Version Number') + put_key_parser.add_argument('--key-id', type=auto_int, required=True, help='Key Identifier (base)') + put_key_parser.add_argument('--key-type', choices=KeyType.ksymapping.values(), action='append', required=True, help='Key Type') + put_key_parser.add_argument('--key-data', type=is_hexstr, action='append', required=True, help='Key Data Block') + put_key_parser.add_argument('--key-check', type=is_hexstr, action='append', help='Key Check Value') + @cmd2.with_argparser(put_key_parser) + def do_put_key(self, opts): + """Perform the GlobalPlatform PUT KEY command in order to store a new key on the card. + See GlobalPlatform CardSpecification v2.3 Section 11.8 for details. + + Example (SCP80 KIC/KID/KIK): + put_key --key-version-nr 1 --key-id 0x81 --key-type aes --key-data 000102030405060708090a0b0c0d0e0f + --key-type aes --key-data 101112131415161718191a1b1c1d1e1f + --key-type aes --key-data 202122232425262728292a2b2c2d2e2f + + Example (SCP81 TLS-PSK/KEK): + put_key --key-version-nr 0x40 --key-id 0x81 --key-type tls_psk --key-data 303132333435363738393a3b3c3d3e3f + --key-type des --key-data 404142434445464748494a4b4c4d4e4f + + """ + if len(opts.key_type) != len(opts.key_data): + raise ValueError('There must be an equal number of key-type and key-data arguments') + kdb = [] + for i in range(0, len(opts.key_type)): + if opts.key_check and len(opts.key_check) > i: + kcv = opts.key_check[i] + else: + kcv = '' + kdb.append({'key_type': opts.key_type[i], 'kcb': opts.key_data[i], 'kcv': kcv}) + return self.put_key(opts.old_key_version_nr, opts.key_version_nr, opts.key_id, kdb) + + # Table 11-68: Key Data Field - Format 1 (Basic Format) + KeyDataBasic = GreedyRange(Struct('key_type'/KeyType, + 'kcb'/HexAdapter(Prefixed(Int8ub, GreedyBytes)), + 'kcv'/HexAdapter(Prefixed(Int8ub, GreedyBytes)))) + + def put_key(self, old_kvn:int, kvn: int, kid: int, key_dict: dict) -> bytes: + """Perform the GlobalPlatform PUT KEY command in order to store a new key on the card. + See GlobalPlatform CardSpecification v2.3 Section 11.8 for details.""" + key_data = kvn.to_bytes(1, 'big') + build_construct(ADF_SD.AddlShellCommands.KeyDataBasic, key_dict) + hdr = "80D8%02x%02x%02x" % (old_kvn, kid, len(key_data)) + data, sw = self._cmd.lchan.scc._tp.send_apdu_checksw(hdr + b2h(key_data)) + return data # Card Application of a Security Domain -- To view, visit
https://gerrit.osmocom.org/c/pysim/+/35684?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: Icffe9e7743266d7262fbf440dd361b21eed7c5cf Gerrit-Change-Number: 35684 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-MessageType: newchange
1 year, 5 months
1
0
0
0
[S] Change in pysim[master]: docs: Add missing global_platform store_data command docs
by laforge
laforge has uploaded this change for review. (
https://gerrit.osmocom.org/c/pysim/+/35683?usp=email
) Change subject: docs: Add missing global_platform store_data command docs ...................................................................... docs: Add missing global_platform store_data command docs In If30c5d31b4e7dd60d3a5cfb1d1cbdcf61741a50e we introduced a store_data comamnd, but forgot to add it to the pySim-shell manual. Change-Id: I6039818c2c0c5373b4a4ef1e33e152de7fbbd01a --- M docs/shell.rst 1 file changed, 18 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/83/35683/1 diff --git a/docs/shell.rst b/docs/shell.rst index 7022b5a..89a0d0a 100644 --- a/docs/shell.rst +++ b/docs/shell.rst @@ -941,6 +941,12 @@ :module: pySim.global_platform :func: ADF_SD.AddlShellCommands.get_data_parser +store_data +~~~~~~~~~~ +.. argparse:: + :module: pySim.global_platform + :func: ADF_SD.AddlShellCommands.store_data_parser + eUICC ISD-R commands -------------------- -- To view, visit
https://gerrit.osmocom.org/c/pysim/+/35683?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: I6039818c2c0c5373b4a4ef1e33e152de7fbbd01a Gerrit-Change-Number: 35683 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-MessageType: newchange
1 year, 5 months
1
0
0
0
[S] Change in ...osmo-epdg[master]: Forward IP Address from CreateSessionresponse in GSUP EPDG Tunnel Result
by pespin
pespin has submitted this change. (
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35658?usp=email
) Change subject: Forward IP Address from CreateSessionresponse in GSUP EPDG Tunnel Result ...................................................................... Forward IP Address from CreateSessionresponse in GSUP EPDG Tunnel Result Related: OS#6091 Change-Id: I2a9130d242830daa826414a287f54862752017d2 --- M rebar.config M rebar.lock M src/gsup_server.erl 3 files changed, 29 insertions(+), 5 deletions(-) Approvals: laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified pespin: Looks good to me, approved diff --git a/rebar.config b/rebar.config index a2db3ea..19688f5 100644 --- a/rebar.config +++ b/rebar.config @@ -6,7 +6,7 @@ {lager, {git, "
https://github.com/erlang-lager/lager
", {tag, "3.9.2"}}}, {gtplib, "3.2.0"}, {osmo_ss7, {git, "
https://gitea.osmocom.org/erlang/osmo_ss7
", {ref, "9f294d3612f998860004820d1d85b4264721577b"}}}, - {osmo_gsup, {git, "
https://gitea.osmocom.org/erlang/osmo_gsup
", {branch, "lynxis/epdg"}}} + {osmo_gsup, {git, "
https://gerrit.osmocom.org/erlang/osmo_gsup
", {branch, "osmocom/epdg"}}} ]}. {minimum_otp_vsn, "20.3"}. diff --git a/rebar.lock b/rebar.lock index 322e84d..d74d179 100644 --- a/rebar.lock +++ b/rebar.lock @@ -11,8 +11,8 @@ {ref,"459a3b2cdd9eadd29e5a7ce5c43932f5ccd6eb88"}}, 0}, {<<"osmo_gsup">>, - {git,"
https://gitea.osmocom.org/erlang/osmo_gsup
", - {ref,"07672d8ab1608aa9c9e50ca035521876558fcd42"}}, + {git,"
https://gerrit.osmocom.org/erlang/osmo_gsup
", + {ref,"1a064fa6aece492352271ae164b29262d66f6b6d"}}, 0}, {<<"osmo_ss7">>, {git,"
https://gitea.osmocom.org/erlang/osmo_ss7
", diff --git a/src/gsup_server.erl b/src/gsup_server.erl index 030a328..b8ed637 100644 --- a/src/gsup_server.erl +++ b/src/gsup_server.erl @@ -38,6 +38,8 @@ -include_lib("diameter_3gpp_ts29_273_swx.hrl"). -include_lib("osmo_ss7/include/ipa.hrl"). +-include_lib("osmo_gsup/include/gsup_protocol.hrl"). +-include_lib("gtplib/include/gtp_packet.hrl"). -define(IPAC_PROTO_EXT_GSUP, {osmo, 5}). @@ -179,10 +181,22 @@ lager:info("GSUP: Rx ~p~n", [GsupMsgRx]), Result = epdg_gtpc_s2b:create_session_req(Imsi), case Result of - {ok, _} -> + {ok, #gtp{version = v2, type = create_session_response}} -> + {ok, CreateSessResp} = Result, + IEs = CreateSessResp#gtp.ie, + %%#{{v2_bearer_context,0} := BearerMap} = IEs, + #{{v2_pdn_address_allocation,0} := Paa} = IEs, + PdpAddress = #{pdp_type_org => 1, pdp_type_nr => 16#21, address => #{ ipv4 => Paa#v2_pdn_address_allocation.address}}, + PdpInfo = #{pdp_context_id => 0, + pdp_address => PdpAddress, + access_point_name => "foobar.apn", + quality_of_service => <<0, 0, 0>>, + pdp_charging => 0}, Resp = #{message_type => epdg_tunnel_result, imsi => Imsi, - message_class => 5 + message_class => 5, + pdp_info_complete => true, + pdp_info_list => [PdpInfo] }; {error, _} -> Resp = #{message_type => epdg_tunnel_error, -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35658?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: I2a9130d242830daa826414a287f54862752017d2 Gerrit-Change-Number: 35658 Gerrit-PatchSet: 2 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: lynxis lazus <lynxis(a)fe80.eu> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 year, 5 months
1
0
0
0
[M] Change in ...osmo-epdg[master]: Make CreateSession Req+Resp procedure async
by pespin
pespin has submitted this change. (
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35660?usp=email
) Change subject: Make CreateSession Req+Resp procedure async ...................................................................... Make CreateSession Req+Resp procedure async Change-Id: Ib42ed08afa4a06149d2d72ac64487eec808e260f --- M src/epdg_gtpc_s2b.erl M src/ue_fsm.erl 2 files changed, 44 insertions(+), 32 deletions(-) Approvals: laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified pespin: Looks good to me, approved diff --git a/src/epdg_gtpc_s2b.erl b/src/epdg_gtpc_s2b.erl index fe07a42..fc41351 100644 --- a/src/epdg_gtpc_s2b.erl +++ b/src/epdg_gtpc_s2b.erl @@ -86,6 +86,7 @@ -record(gtp_session, { imsi :: binary(), + pid :: pid(), apn :: binary(), ue_ip :: inet:ip_address(), local_control_tei = 0 :: non_neg_integer(), @@ -136,32 +137,15 @@ end. create_session_req(Imsi) -> - gen_server:call(?SERVER, - {gtpc_create_session_req, {Imsi}}). + gen_server:call(?SERVER, {gtpc_create_session_req, {Imsi}}). -handle_call({gtpc_create_session_req, {Imsi}}, _From, State0) -> - {Sess0, State1} = find_or_new_gtp_session(Imsi, State0), +handle_call({gtpc_create_session_req, {Imsi}}, {Pid, _Tag} = _From, State0) -> + {Sess0, State1} = find_or_new_gtp_session(Imsi, Pid, State0), Req = gen_create_session_request(Sess0, State1), %TODO: increment State.seq_no. tx_gtp(Req, State1), lager:debug("Waiting for CreateSessionResponse~n", []), - receive - {udp, _Socket, IP, InPortNo, RxMsg} -> - try - Resp = gtp_packet:decode(RxMsg), - lager:info("s2b: Rx from IP ~p port ~p ~p~n", [IP, InPortNo, Resp]), - Sess1 = update_gtp_session_from_create_session_response(Resp, Sess0), - lager:info("s2b: Updated Session after create_session_response: ~p~n", [Sess1]), - State2 = update_gtp_session(Sess0, Sess1, State1), - {reply, {ok, Resp}, State2} - catch Any -> - lager:error("Error sending message to receiver, ERROR: ~p~n", [Any]), - {reply, {error, decode_failure}, State1} - end - after 5000 -> - lager:error("Timeout waiting for CreateSessionResponse for ~p~n", [Req]), - {reply, timeout, State1} - end. + {reply, ok, State1}. %% @callback gen_server handle_cast(stop, State) -> @@ -199,13 +183,14 @@ %% Internal Function Definitions %% ------------------------------------------------------------------ -new_gtp_session(Imsi, State) -> +new_gtp_session(Imsi, Pid, State) -> % TODO: find non-used local TEI inside State Bearer = #gtp_bearer{ ebi = 5, local_data_tei = State#gtp_state.next_local_data_tei }, Sess = #gtp_session{imsi = Imsi, + pid = Pid, apn = ?APN, local_control_tei = State#gtp_state.next_local_control_tei, bearer = Bearer @@ -224,13 +209,13 @@ undefined, State#gtp_state.sessions). -find_or_new_gtp_session(Imsi, State) -> +find_or_new_gtp_session(Imsi, Pid, State) -> Sess = find_gtp_session_by_imsi(Imsi, State), case Sess of #gtp_session{imsi = Imsi} -> {Sess, State}; undefined -> - new_gtp_session(Imsi, State) + new_gtp_session(Imsi, Pid, State) end. update_gtp_session(OldSess, NewSess, State) -> @@ -277,6 +262,20 @@ connect(Address) -> connect(?SVC_NAME, Address). +rx_gtp(Resp = #gtp{version = v2, type = create_session_response}, State0) -> + Sess0 = find_gtp_session_by_local_teic(Resp#gtp.tei, State0), + case Sess0 of + undefined -> + lager:error("Rx unknown TEI ~p: ~p~n", [Resp#gtp.tei, Resp]), + {noreply, State0}; + Sess0 -> + Sess1 = update_gtp_session_from_create_session_response(Resp, Sess0), + lager:info("s2b: Updated Session after create_session_response: ~p~n", [Sess1]), + State1 = update_gtp_session(Sess0, Sess1, State0), + ue_fsm:received_gtpc_create_session_response(Sess0#gtp_session.pid, {ok, Resp}), + {noreply, State1} + end; + rx_gtp(Req = #gtp{version = v2, type = delete_bearer_request}, State) -> Sess = find_gtp_session_by_local_teic(Req#gtp.tei, State), case Sess of @@ -289,6 +288,7 @@ State1 = delete_gtp_session(Sess, State), {noreply, State1} end; + rx_gtp(Req, State) -> lager:error("S2b: UNIMPLEMENTED Rx: ~p~n", [Req]), {noreply, State}. diff --git a/src/ue_fsm.erl b/src/ue_fsm.erl index 0fe6992..f6b2b7e 100644 --- a/src/ue_fsm.erl +++ b/src/ue_fsm.erl @@ -36,7 +36,7 @@ -export([start_link/1]). -export([init/1,callback_mode/0,terminate/3]). --export([auth_request/1, lu_request/1, tunnel_request/1]). +-export([auth_request/1, lu_request/1, tunnel_request/1, received_gtpc_create_session_response/2]). -export([state_new/3,state_authenticated/3]). -record(ue_fsm_data, { @@ -60,6 +60,10 @@ lager:info("ue_fsm tunnel_request~n", []), gen_statem:cast(Pid, tunnel_request). +received_gtpc_create_session_response(Pid, Msg) -> + lager:info("ue_fsm received_gtpc_create_session_response ~p~n", [Msg]), + gen_statem:cast(Pid, {received_gtpc_create_session_response, Msg}). + init(Imsi) -> lager:info("ue_fsm init(~p)~n", [Imsi]), Data = #ue_fsm_data{imsi = Imsi}, @@ -96,14 +100,13 @@ state_authenticated(cast, tunnel_request, Data) -> lager:info("ue_fsm state_authenticated event=tunnel_request, ~p~n", [Data]), - Result = epdg_gtpc_s2b:create_session_req(Data#ue_fsm_data.imsi), + epdg_gtpc_s2b:create_session_req(Data#ue_fsm_data.imsi), + {keep_state, Data}; + +state_authenticated(cast, {received_gtpc_create_session_response, Result}, Data) -> + lager:info("ue_fsm state_authenticated event=received_gtpc_create_session_response, ~p~n", [Data]), gsup_server:tunnel_response(Data#ue_fsm_data.imsi, Result), - case Result of - {ok, _} -> - {keep_state, Data}; - {error, Err} -> - {stop, Err, Data} - end; + {keep_state, Data}; state_authenticated(cast, _Whatever, Data) -> lager:info("ue_fsm state_authenticated event=auth_request, ~p~n", [Data]), -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35660?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: Ib42ed08afa4a06149d2d72ac64487eec808e260f Gerrit-Change-Number: 35660 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 year, 5 months
1
0
0
0
[L] Change in ...osmo-epdg[master]: Introduce ue_fsm
by pespin
pespin has submitted this change. (
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35659?usp=email
) Change subject: Introduce ue_fsm ...................................................................... Introduce ue_fsm Decouple gsup_server from other protocols. Change-Id: I0c960c4c250458384ed706a99582ec52083019f6 --- M src/gsup_server.erl A src/ue_fsm.erl 2 files changed, 269 insertions(+), 70 deletions(-) Approvals: laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified dexter: Looks good to me, but someone else must approve pespin: Looks good to me, approved diff --git a/src/gsup_server.erl b/src/gsup_server.erl index b8ed637..5fe227c 100644 --- a/src/gsup_server.erl +++ b/src/gsup_server.erl @@ -41,19 +41,28 @@ -include_lib("osmo_gsup/include/gsup_protocol.hrl"). -include_lib("gtplib/include/gtp_packet.hrl"). +-define(SERVER, ?MODULE). + -define(IPAC_PROTO_EXT_GSUP, {osmo, 5}). -record(gsups_state, { lsocket, % listening socket lport, % local port. only interesting if we bind with port 0 socket, % current active socket. we only support a single tcp connection - ccm_options % ipa ccm options + ccm_options, % ipa ccm options + ues = sets:new() + }). + +-record(gsups_ue, { + imsi :: binary(), + pid :: pid() }). -export([start_link/3]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2]). -export([code_change/3, terminate/2]). +-export([auth_response/2, lu_response/2, tunnel_response/2]). % TODO: -spec dia_sip2gsup('SIP-Auth-Data-Item'()) -> #'GSUPAuthTuple'{}. dia_sip2gsup(#'SIP-Auth-Data-Item'{'SIP-Authenticate' = [Authenticate], 'SIP-Authorization' = [Authorization], @@ -71,7 +80,7 @@ %% ------------------------------------------------------------------ start_link(ServerAddr, ServerPort, Options) -> - gen_server:start_link(?MODULE, [ServerAddr, ServerPort, Options], [{debug, [trace]}]). + gen_server:start_link({local, ?SERVER}, ?MODULE, [ServerAddr, ServerPort, Options], [{debug, [trace]}]). %% ------------------------------------------------------------------ %% gen_server Function Definitions @@ -105,20 +114,76 @@ end. % send a given GSUP message and synchronously wait for message type ExpRes or ExpErr -handle_call({transceive_gsup, GsupMsgTx, ExpRes, ExpErr}, _From, State) -> - Socket = State#gsups_state.socket, - {ok, Imsi} = maps:find(imsi, GsupMsgTx), - ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, GsupMsgTx), - % selective receive for only those GSUP responses we expect - receive - {ipa, Socket, ?IPAC_PROTO_EXT_GSUP, GsupMsgRx = #{message_type := ExpRes, imsi := Imsi}} -> - {reply, GsupMsgRx, State}; +handle_call(Info, _From, State) -> + error_logger:error_report(["unknown handle_call", {module, ?MODULE}, {info, Info}, {state, State}]), + {reply, error, not_implemented}. - {ipa, Socket, ?IPAC_PROTO_EXT_GSUP, GsupMsgRx = #{message_type := ExpErr, imsi := Imsi}} -> - {reply, GsupMsgRx, State} - after 5000 -> - {reply, timeout, State} - end. +handle_cast({auth_response, {Imsi, Auth}}, State) -> + lager:info("auth_response for ~p: ~p~n", [Imsi, Auth]), + Socket = State#gsups_state.socket, + case Auth of + {ok, Mar} -> SipAuthTuples = Mar#'MAA'.'SIP-Auth-Data-Item', + % AuthTuples = dia_sip2gsup(SipAuthTuples), + Resp = #{message_type => send_auth_info_res, + message_class => 5, + imsi => list_to_binary(Mar#'MAA'.'User-Name'), + auth_tuples => lists:map(fun dia_sip2gsup/1, SipAuthTuples) + }; + {error, _} -> Resp = #{message_type => send_auth_info_err, imsi => Imsi, message_class => 5, cause => 16#11} + end, + lager:info("GSUP: Tx ~p~n", [Resp]), + ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp), + {noreply, State}; + +handle_cast({lu_response, {Imsi, Result}}, State) -> + lager:info("lu_response for ~p: ~p~n", [Imsi, Result]), + Socket = State#gsups_state.socket, + case Result of + {ok, _Sar} -> Resp = #{message_type => location_upd_res, + imsi => Imsi, + message_class => 5 + }; + {error, _} -> Resp = #{message_type => location_upd_err, + imsi => Imsi, + message_class => 5, + cause => 16#11 % FIXME: Use proper defines as cause code and use Network failure + } + end, + lager:info("GSUP: Tx ~p~n", [Resp]), + ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp), + {noreply, State}; + +handle_cast({tunnel_response, {Imsi, Result}}, State) -> + lager:info("tunnel_response for ~p: ~p~n", [Imsi, Result]), + Socket = State#gsups_state.socket, + case Result of + {ok, #gtp{version = v2, type = create_session_response}} -> + {ok, CreateSessResp} = Result, + IEs = CreateSessResp#gtp.ie, + %%#{{v2_bearer_context,0} := BearerMap} = IEs, + #{{v2_pdn_address_allocation,0} := Paa} = IEs, + PdpAddress = #{pdp_type_org => 1, pdp_type_nr => 16#21, address => #{ ipv4 => Paa#v2_pdn_address_allocation.address}}, + PdpInfo = #{pdp_context_id => 0, + pdp_address => PdpAddress, + access_point_name => "foobar.apn", + quality_of_service => <<0, 0, 0>>, + pdp_charging => 0}, + Resp = #{message_type => epdg_tunnel_result, + imsi => Imsi, + message_class => 5, + pdp_info_complete => true, + pdp_info_list => [PdpInfo] + }; + {error, _} -> + Resp = #{message_type => epdg_tunnel_error, + imsi => Imsi, + message_class => 5, + cause => 16#11 % FIXME: Use proper defines as cause code and use Network failure + } + end, + lager:info("GSUP: Tx ~p~n", [Resp]), + ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp), + {noreply, State}; handle_cast(Info, S) -> error_logger:error_report(["unknown handle_cast", {module, ?MODULE}, {info, Info}, {state, S}]), @@ -140,74 +205,47 @@ {noreply, S#gsups_state{socket=Socket}}; % send auth info / requesting authentication tuples -handle_info({ipa, Socket, ?IPAC_PROTO_EXT_GSUP, GsupMsgRx = #{message_type := send_auth_info_req, imsi := Imsi}}, S) -> - Auth = auth_handler:auth_request(Imsi), - case Auth of - {ok, Mar} -> SipAuthTuples = Mar#'MAA'.'SIP-Auth-Data-Item', - % AuthTuples = dia_sip2gsup(SipAuthTuples), - Resp = #{message_type => send_auth_info_res, - message_class => 5, - imsi => list_to_binary(Mar#'MAA'.'User-Name'), - auth_tuples => lists:map(fun dia_sip2gsup/1, SipAuthTuples) - }; - {error, _} -> Resp = #{message_type => send_auth_info_err, imsi => Imsi, message_class => 5, cause => 16#11} - end, - lager:info("auth tuples: ~p ~n", [Resp]), - ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp), - {noreply, S}; +handle_info({ipa, _Socket, ?IPAC_PROTO_EXT_GSUP, _GsupMsgRx = #{message_type := send_auth_info_req, imsi := Imsi}}, State0) -> + {UE, State1} = find_or_new_gsups_ue(Imsi, State0), + ue_fsm:auth_request(UE#gsups_ue.pid), + {noreply, State1}; % location update request / when a UE wants to connect to a specific APN. This will trigger a AAA->HLR Request Server Assignment Request % FIXME: add APN instead of hardcoded internet -handle_info({ipa, Socket, ?IPAC_PROTO_EXT_GSUP, GsupMsgRx = #{message_type := location_upd_req, imsi := Imsi}}, S) -> - % FIXME: use enum for Server-Assignment-Type => REGISTERING - Result = epdg_diameter_swx:server_assignment_request(Imsi, 1, "internet"), - case Result of - {ok, Sar} -> Resp = #{message_type => location_upd_res, - imsi => Imsi, - message_class => 5 - }; - {error, _} -> Resp = #{message_type => location_upd_err, - imsi => Imsi, - message_class => 5, - cause => 16#11 % FIXME: Use proper defines as cause code and use Network failure - } +handle_info({ipa, Socket, ?IPAC_PROTO_EXT_GSUP, _GsupMsgRx = #{message_type := location_upd_req, imsi := Imsi}}, State) -> + UE = find_gsups_ue_by_imsi(Imsi, State), + case UE of + #gsups_ue{imsi = Imsi} -> + ue_fsm:lu_request(UE#gsups_ue.pid); + undefined -> + Resp = #{message_type => location_upd_err, + imsi => Imsi, + message_class => 5, + cause => 16#11 % FIXME: Use proper defines as cause code and use Network failure + }, + lager:info("GSUP: Tx ~p~n", [Resp]), + ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp) end, - ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp), - {noreply, S}; + {noreply, State}; % epdg tunnel request / trigger the establishment to the PGW and prepares everything for the user traffic to flow % When sending a epdg_tunnel_response everything must be ready for the UE traffic -handle_info({ipa, Socket, ?IPAC_PROTO_EXT_GSUP, GsupMsgRx = #{message_type := epdg_tunnel_request, imsi := Imsi}}, S) -> +handle_info({ipa, Socket, ?IPAC_PROTO_EXT_GSUP, GsupMsgRx = #{message_type := epdg_tunnel_request, imsi := Imsi}}, State) -> lager:info("GSUP: Rx ~p~n", [GsupMsgRx]), - Result = epdg_gtpc_s2b:create_session_req(Imsi), - case Result of - {ok, #gtp{version = v2, type = create_session_response}} -> - {ok, CreateSessResp} = Result, - IEs = CreateSessResp#gtp.ie, - %%#{{v2_bearer_context,0} := BearerMap} = IEs, - #{{v2_pdn_address_allocation,0} := Paa} = IEs, - PdpAddress = #{pdp_type_org => 1, pdp_type_nr => 16#21, address => #{ ipv4 => Paa#v2_pdn_address_allocation.address}}, - PdpInfo = #{pdp_context_id => 0, - pdp_address => PdpAddress, - access_point_name => "foobar.apn", - quality_of_service => <<0, 0, 0>>, - pdp_charging => 0}, - Resp = #{message_type => epdg_tunnel_result, - imsi => Imsi, - message_class => 5, - pdp_info_complete => true, - pdp_info_list => [PdpInfo] - }; - {error, _} -> + UE = find_gsups_ue_by_imsi(Imsi, State), + case UE of + #gsups_ue{imsi = Imsi} -> + ue_fsm:tunnel_request(UE#gsups_ue.pid); + undefined -> Resp = #{message_type => epdg_tunnel_error, imsi => Imsi, message_class => 5, cause => 16#11 % FIXME: Use proper defines as cause code and use Network failure - } + }, + lager:info("GSUP: Tx ~p~n", [Resp]), + ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp) end, - lager:info("GSUP: Tx ~p~n", [Resp]), - ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp), - {noreply, S}; + {noreply, State}; handle_info(Info, S) -> error_logger:error_report(["unknown handle_info", {module, ?MODULE}, {info, Info}, {state, S}]), @@ -218,3 +256,43 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. + +auth_response(Imsi, Auth) -> + lager:info("auth_response(~p): ~p~n", [Imsi, Auth]), + gen_server:cast(?SERVER, {auth_response, {Imsi, Auth}}). + +lu_response(Imsi, Result) -> + lager:info("lu_response(~p): ~p~n", [Imsi, Result]), + gen_server:cast(?SERVER, {lu_response, {Imsi, Result}}). + +tunnel_response(Imsi, Result) -> + lager:info("tunnel_response(~p): ~p~n", [Imsi, Result]), + gen_server:cast(?SERVER, {tunnel_response, {Imsi, Result}}). + +%% ------------------------------------------------------------------ +%% Internal Function Definitions +%% ------------------------------------------------------------------ + +new_gsups_ue(Imsi, State) -> + {ok, Pid} = ue_fsm:start_link(Imsi), + UE = #gsups_ue{imsi = Imsi, pid = Pid}, + NewSt = State#gsups_state{ues = sets:add_element(UE, State#gsups_state.ues)}, + {UE, NewSt}. + +% returns gsups_ue if found, undefined it not +find_gsups_ue_by_imsi(Imsi, State) -> + sets:fold( + fun(UEsIt = #gsups_ue{imsi = Imsi}, _AccIn) -> UEsIt; + (_, AccIn) -> AccIn + end, + undefined, + State#gsups_state.ues). + +find_or_new_gsups_ue(Imsi, State) -> + UE = find_gsups_ue_by_imsi(Imsi, State), + case UE of + #gsups_ue{imsi = Imsi} -> + {UE, State}; + undefined -> + new_gsups_ue(Imsi, State) + end. \ No newline at end of file diff --git a/src/ue_fsm.erl b/src/ue_fsm.erl new file mode 100644 index 0000000..0fe6992 --- /dev/null +++ b/src/ue_fsm.erl @@ -0,0 +1,110 @@ +% 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(ue_fsm). +-behaviour(gen_statem). +-define(NAME, ue_fsm). + +-export([start_link/1]). +-export([init/1,callback_mode/0,terminate/3]). +-export([auth_request/1, lu_request/1, tunnel_request/1]). +-export([state_new/3,state_authenticated/3]). + +-record(ue_fsm_data, { + imsi + }). + +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]}]). + +auth_request(Pid) -> + lager:info("ue_fsm auth_request~n", []), + gen_statem:cast(Pid, auth_request). + +lu_request(Pid) -> + lager:info("ue_fsm lu_request~n", []), + gen_statem:cast(Pid, lu_request). + +tunnel_request(Pid) -> + lager:info("ue_fsm tunnel_request~n", []), + gen_statem:cast(Pid, tunnel_request). + +init(Imsi) -> + lager:info("ue_fsm init(~p)~n", [Imsi]), + Data = #ue_fsm_data{imsi = Imsi}, + {ok, state_new, Data}. + +callback_mode() -> + state_functions. + +terminate(Reason, State, Data) -> + lager:info("terminating ~p with reason ~p state=~p, ~p~n", [?MODULE, Reason, State, Data]), + ok. + +state_new(cast, auth_request, Data) -> + lager:info("ue_fsm state_new event=auth_request, ~p~n", [Data]), + Auth = auth_handler:auth_request(Data#ue_fsm_data.imsi), + gsup_server:auth_response(Data#ue_fsm_data.imsi, Auth), + case Auth of + {ok, _} -> + {next_state, state_authenticated, Data}; + {error, Err} -> + {stop, Err, Data} + end. + +state_authenticated(cast, lu_request, Data) -> + lager:info("ue_fsm state_authenticated event=lu_request, ~p~n", [Data]), + Result = epdg_diameter_swx:server_assignment_request(Data#ue_fsm_data.imsi, 1, "internet"), + gsup_server:lu_response(Data#ue_fsm_data.imsi, Result), + case Result of + {ok, _} -> + {keep_state, Data}; + {error, Err} -> + {stop, Err, Data} + end; + +state_authenticated(cast, tunnel_request, Data) -> + lager:info("ue_fsm state_authenticated event=tunnel_request, ~p~n", [Data]), + Result = epdg_gtpc_s2b:create_session_req(Data#ue_fsm_data.imsi), + gsup_server:tunnel_response(Data#ue_fsm_data.imsi, Result), + case Result of + {ok, _} -> + {keep_state, Data}; + {error, Err} -> + {stop, Err, Data} + end; + +state_authenticated(cast, _Whatever, Data) -> + lager:info("ue_fsm state_authenticated event=auth_request, ~p~n", [Data]), + {keep_state, Data}. \ No newline at end of file -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35659?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: I0c960c4c250458384ed706a99582ec52083019f6 Gerrit-Change-Number: 35659 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: dexter <pmaier(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 year, 5 months
1
0
0
0
[S] Change in ...osmo-epdg[master]: gsup_server: Use new GSUP Cause defines from osmo_gsup
by pespin
pespin has submitted this change. (
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35673?usp=email
) Change subject: gsup_server: Use new GSUP Cause defines from osmo_gsup ...................................................................... gsup_server: Use new GSUP Cause defines from osmo_gsup Change-Id: Ie19a0d0b81e0a264401ea37e0cfd74802aee68fe --- M rebar.lock M src/gsup_server.erl 2 files changed, 15 insertions(+), 6 deletions(-) Approvals: pespin: Looks good to me, approved Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve diff --git a/rebar.lock b/rebar.lock index d74d179..a542cbc 100644 --- a/rebar.lock +++ b/rebar.lock @@ -12,7 +12,7 @@ 0}, {<<"osmo_gsup">>, {git,"
https://gerrit.osmocom.org/erlang/osmo_gsup
", - {ref,"1a064fa6aece492352271ae164b29262d66f6b6d"}}, + {ref,"1391d074f610e736368319d56fd958fa36e3addf"}}, 0}, {<<"osmo_ss7">>, {git,"
https://gitea.osmocom.org/erlang/osmo_ss7
", diff --git a/src/gsup_server.erl b/src/gsup_server.erl index 5fe227c..a110b40 100644 --- a/src/gsup_server.erl +++ b/src/gsup_server.erl @@ -129,7 +129,7 @@ imsi => list_to_binary(Mar#'MAA'.'User-Name'), auth_tuples => lists:map(fun dia_sip2gsup/1, SipAuthTuples) }; - {error, _} -> Resp = #{message_type => send_auth_info_err, imsi => Imsi, message_class => 5, cause => 16#11} + {error, _} -> Resp = #{message_type => send_auth_info_err, imsi => Imsi, message_class => 5, cause => ?GSUP_CAUSE_NET_FAIL} end, lager:info("GSUP: Tx ~p~n", [Resp]), ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp), @@ -146,7 +146,7 @@ {error, _} -> Resp = #{message_type => location_upd_err, imsi => Imsi, message_class => 5, - cause => 16#11 % FIXME: Use proper defines as cause code and use Network failure + cause => ?GSUP_CAUSE_NET_FAIL } end, lager:info("GSUP: Tx ~p~n", [Resp]), @@ -178,7 +178,7 @@ Resp = #{message_type => epdg_tunnel_error, imsi => Imsi, message_class => 5, - cause => 16#11 % FIXME: Use proper defines as cause code and use Network failure + cause => ?GSUP_CAUSE_NET_FAIL } end, lager:info("GSUP: Tx ~p~n", [Resp]), @@ -221,7 +221,7 @@ Resp = #{message_type => location_upd_err, imsi => Imsi, message_class => 5, - cause => 16#11 % FIXME: Use proper defines as cause code and use Network failure + cause => ?GSUP_CAUSE_IMSI_UNKNOWN }, lager:info("GSUP: Tx ~p~n", [Resp]), ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp) @@ -240,7 +240,7 @@ Resp = #{message_type => epdg_tunnel_error, imsi => Imsi, message_class => 5, - cause => 16#11 % FIXME: Use proper defines as cause code and use Network failure + cause => ?GSUP_CAUSE_IMSI_UNKNOWN }, lager:info("GSUP: Tx ~p~n", [Resp]), ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp) -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35673?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: Ie19a0d0b81e0a264401ea37e0cfd74802aee68fe Gerrit-Change-Number: 35673 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 year, 5 months
1
0
0
0
[S] Change in ...osmo-epdg[master]: gsup_server: Introduce tx_gsup() internal function
by pespin
pespin has submitted this change. (
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35674?usp=email
) Change subject: gsup_server: Introduce tx_gsup() internal function ...................................................................... gsup_server: Introduce tx_gsup() internal function Change-Id: I95d37182da89e39993eb7d5aaf63446e5f99ae2a --- M src/gsup_server.erl 1 file changed, 19 insertions(+), 10 deletions(-) Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved laforge: Looks good to me, but someone else must approve diff --git a/src/gsup_server.erl b/src/gsup_server.erl index a110b40..521d4c3 100644 --- a/src/gsup_server.erl +++ b/src/gsup_server.erl @@ -131,8 +131,7 @@ }; {error, _} -> Resp = #{message_type => send_auth_info_err, imsi => Imsi, message_class => 5, cause => ?GSUP_CAUSE_NET_FAIL} end, - lager:info("GSUP: Tx ~p~n", [Resp]), - ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp), + tx_gsup(Socket, Resp), {noreply, State}; handle_cast({lu_response, {Imsi, Result}}, State) -> @@ -149,8 +148,7 @@ cause => ?GSUP_CAUSE_NET_FAIL } end, - lager:info("GSUP: Tx ~p~n", [Resp]), - ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp), + tx_gsup(Socket, Resp), {noreply, State}; handle_cast({tunnel_response, {Imsi, Result}}, State) -> @@ -181,8 +179,7 @@ cause => ?GSUP_CAUSE_NET_FAIL } end, - lager:info("GSUP: Tx ~p~n", [Resp]), - ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp), + tx_gsup(Socket, Resp), {noreply, State}; handle_cast(Info, S) -> @@ -223,8 +220,7 @@ message_class => 5, cause => ?GSUP_CAUSE_IMSI_UNKNOWN }, - lager:info("GSUP: Tx ~p~n", [Resp]), - ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp) + tx_gsup(Socket, Resp) end, {noreply, State}; @@ -242,8 +238,7 @@ message_class => 5, cause => ?GSUP_CAUSE_IMSI_UNKNOWN }, - lager:info("GSUP: Tx ~p~n", [Resp]), - ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Resp) + tx_gsup(Socket, Resp) end, {noreply, State}; @@ -273,6 +268,11 @@ %% Internal Function Definitions %% ------------------------------------------------------------------ +tx_gsup(Socket, Msg) -> + lager:info("GSUP: Tx ~p~n", [Msg]), + ipa_proto:send(Socket, ?IPAC_PROTO_EXT_GSUP, Msg). + + new_gsups_ue(Imsi, State) -> {ok, Pid} = ue_fsm:start_link(Imsi), UE = #gsups_ue{imsi = Imsi, pid = Pid}, -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35674?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: I95d37182da89e39993eb7d5aaf63446e5f99ae2a Gerrit-Change-Number: 35674 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 year, 5 months
1
0
0
0
[M] Change in ...osmo-epdg[master]: Use call() instead of cast() in ue_fsm
by pespin
pespin has submitted this change. (
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35675?usp=email
) Change subject: Use call() instead of cast() in ue_fsm ...................................................................... Use call() instead of cast() in ue_fsm This allows accounting for problems in the FSM from the calling code, and act accordingly, eg. rejecting a message. Change-Id: I235d3c8fb3a863d288b5433c39e0da65f747936b --- M src/gsup_server.erl M src/ue_fsm.erl 2 files changed, 90 insertions(+), 27 deletions(-) Approvals: laforge: Looks good to me, but someone else must approve pespin: Looks good to me, approved Jenkins Builder: Verified diff --git a/src/gsup_server.erl b/src/gsup_server.erl index 521d4c3..30e8864 100644 --- a/src/gsup_server.erl +++ b/src/gsup_server.erl @@ -202,9 +202,18 @@ {noreply, S#gsups_state{socket=Socket}}; % send auth info / requesting authentication tuples -handle_info({ipa, _Socket, ?IPAC_PROTO_EXT_GSUP, _GsupMsgRx = #{message_type := send_auth_info_req, imsi := Imsi}}, State0) -> +handle_info({ipa, Socket, ?IPAC_PROTO_EXT_GSUP, _GsupMsgRx = #{message_type := send_auth_info_req, imsi := Imsi}}, State0) -> {UE, State1} = find_or_new_gsups_ue(Imsi, State0), - ue_fsm:auth_request(UE#gsups_ue.pid), + case ue_fsm:auth_request(UE#gsups_ue.pid) of + ok -> ok; + {error, _} -> + Resp = #{message_type => send_auth_info_err, + imsi => Imsi, + message_class => 5, + cause => ?GSUP_CAUSE_NET_FAIL + }, + tx_gsup(Socket, Resp) + end, {noreply, State1}; % location update request / when a UE wants to connect to a specific APN. This will trigger a AAA->HLR Request Server Assignment Request @@ -212,15 +221,24 @@ handle_info({ipa, Socket, ?IPAC_PROTO_EXT_GSUP, _GsupMsgRx = #{message_type := location_upd_req, imsi := Imsi}}, State) -> UE = find_gsups_ue_by_imsi(Imsi, State), case UE of - #gsups_ue{imsi = Imsi} -> - ue_fsm:lu_request(UE#gsups_ue.pid); - undefined -> + #gsups_ue{imsi = Imsi} -> + case ue_fsm:lu_request(UE#gsups_ue.pid) of + ok -> ok; + {error, _} -> Resp = #{message_type => location_upd_err, imsi => Imsi, message_class => 5, - cause => ?GSUP_CAUSE_IMSI_UNKNOWN + cause => ?GSUP_CAUSE_NET_FAIL }, tx_gsup(Socket, Resp) + end; + undefined -> + Resp = #{message_type => location_upd_err, + imsi => Imsi, + message_class => 5, + cause => ?GSUP_CAUSE_IMSI_UNKNOWN + }, + tx_gsup(Socket, Resp) end, {noreply, State}; @@ -230,15 +248,24 @@ lager:info("GSUP: Rx ~p~n", [GsupMsgRx]), UE = find_gsups_ue_by_imsi(Imsi, State), case UE of - #gsups_ue{imsi = Imsi} -> - ue_fsm:tunnel_request(UE#gsups_ue.pid); - undefined -> + #gsups_ue{imsi = Imsi} -> + case ue_fsm:tunnel_request(UE#gsups_ue.pid) of + ok -> ok; + {error, _} -> Resp = #{message_type => epdg_tunnel_error, - imsi => Imsi, - message_class => 5, - cause => ?GSUP_CAUSE_IMSI_UNKNOWN + imsi => Imsi, + message_class => 5, + cause => ?GSUP_CAUSE_NET_FAIL }, tx_gsup(Socket, Resp) + end; + undefined -> + Resp = #{message_type => epdg_tunnel_error, + imsi => Imsi, + message_class => 5, + cause => ?GSUP_CAUSE_IMSI_UNKNOWN + }, + tx_gsup(Socket, Resp) end, {noreply, State}; diff --git a/src/ue_fsm.erl b/src/ue_fsm.erl index f6b2b7e..c0b8872 100644 --- a/src/ue_fsm.erl +++ b/src/ue_fsm.erl @@ -50,19 +50,39 @@ auth_request(Pid) -> lager:info("ue_fsm auth_request~n", []), - gen_statem:cast(Pid, auth_request). + try + gen_statem:call(Pid, auth_request) + catch + exit:Err -> + {error, Err} + end. lu_request(Pid) -> lager:info("ue_fsm lu_request~n", []), - gen_statem:cast(Pid, lu_request). + try + gen_statem:call(Pid, lu_request) + catch + exit:Err -> + {error, Err} + end. tunnel_request(Pid) -> lager:info("ue_fsm tunnel_request~n", []), - gen_statem:cast(Pid, tunnel_request). + try + gen_statem:call(Pid, tunnel_request) + catch + exit:Err -> + {error, Err} + end. received_gtpc_create_session_response(Pid, Msg) -> lager:info("ue_fsm received_gtpc_create_session_response ~p~n", [Msg]), - gen_statem:cast(Pid, {received_gtpc_create_session_response, Msg}). + try + gen_statem:call(Pid, {received_gtpc_create_session_response, Msg}) + catch + exit:Err -> + {error, Err} + end. init(Imsi) -> lager:info("ue_fsm init(~p)~n", [Imsi]), @@ -76,38 +96,42 @@ lager:info("terminating ~p with reason ~p state=~p, ~p~n", [?MODULE, Reason, State, Data]), ok. -state_new(cast, auth_request, Data) -> +state_new({call, From}, auth_request, Data) -> lager:info("ue_fsm state_new event=auth_request, ~p~n", [Data]), Auth = auth_handler:auth_request(Data#ue_fsm_data.imsi), gsup_server:auth_response(Data#ue_fsm_data.imsi, Auth), case Auth of {ok, _} -> - {next_state, state_authenticated, Data}; + {next_state, state_authenticated, Data, [{reply,From,ok}]}; {error, Err} -> - {stop, Err, Data} + {stop_and_reply, Err, Data, [{reply,From,{error,Err}}]} end. -state_authenticated(cast, lu_request, Data) -> +state_authenticated({call, From}, lu_request, Data) -> lager:info("ue_fsm state_authenticated event=lu_request, ~p~n", [Data]), Result = epdg_diameter_swx:server_assignment_request(Data#ue_fsm_data.imsi, 1, "internet"), gsup_server:lu_response(Data#ue_fsm_data.imsi, Result), case Result of {ok, _} -> - {keep_state, Data}; + {keep_state, Data, [{reply,From,ok}]}; {error, Err} -> - {stop, Err, Data} + {stop, Err, Data, [{reply,From,{error,Err}}]} end; -state_authenticated(cast, tunnel_request, Data) -> +state_authenticated({call, From}, tunnel_request, Data) -> lager:info("ue_fsm state_authenticated event=tunnel_request, ~p~n", [Data]), epdg_gtpc_s2b:create_session_req(Data#ue_fsm_data.imsi), - {keep_state, Data}; + {keep_state, Data, [{reply,From,ok}]}; -state_authenticated(cast, {received_gtpc_create_session_response, Result}, Data) -> +state_authenticated({call, From}, {received_gtpc_create_session_response, Result}, Data) -> lager:info("ue_fsm state_authenticated event=received_gtpc_create_session_response, ~p~n", [Data]), gsup_server:tunnel_response(Data#ue_fsm_data.imsi, Result), - {keep_state, Data}; + {keep_state, Data, [{reply,From,ok}]}; + +state_authenticated({call, From}, _Whatever, Data) -> + lager:error("ue_fsm state_authenticated: Unexpected call event, ~p~n", [Data]), + {keep_state, Data, [{reply,From,ok}]}; state_authenticated(cast, _Whatever, Data) -> - lager:info("ue_fsm state_authenticated event=auth_request, ~p~n", [Data]), + lager:error("ue_fsm state_authenticated: Unexpected cast event, ~p~n", [Data]), {keep_state, Data}. \ No newline at end of file -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35675?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: I235d3c8fb3a863d288b5433c39e0da65f747936b Gerrit-Change-Number: 35675 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 year, 5 months
1
0
0
0
[L] Change in ...osmo-epdg[master]: Implement UE-initiated Detach
by pespin
pespin has submitted this change. (
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35676?usp=email
) Change subject: Implement UE-initiated Detach ...................................................................... Implement UE-initiated Detach This commit is a first step towards implementing the full procedure. It implements handling at the GSUP CEAI interface and operating on the attached PGW to delete the session. No work towards the HSS from AAA server now from PGW to the AAA is done yet. Change-Id: I2e922f76c2fa601c5f61fa23d6df5fb62c3e133d --- M .gitignore A include/gtp_utils.hrl A src/conv.erl M src/epdg_gtpc_s2b.erl M src/gsup_server.erl M src/gtp_utils.erl M src/ue_fsm.erl 7 files changed, 423 insertions(+), 10 deletions(-) Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved diff --git a/.gitignore b/.gitignore index 08ae348..253618b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ _build/ -include/ +include/diameter_* log/ *.beam diff --git a/include/gtp_utils.hrl b/include/gtp_utils.hrl new file mode 100644 index 0000000..453efb0 --- /dev/null +++ b/include/gtp_utils.hrl @@ -0,0 +1,113 @@ +% (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. +% +-hrl_name('gtp_utils.hrl'). + +-define(GTP2_CAUSE_RESERVED, 1). +-define(GTP2_CAUSE_LOCAL_DETACH, 2). +-define(GTP2_CAUSE_COMPLETE_DETACH, 3). +-define(GTP2_CAUSE_RAT_CHANGED_FROM_3GPP_TO_NON_3GPP, 4). +-define(GTP2_CAUSE_ISR_DEACTIVATION, 5). +-define(GTP2_CAUSE_ERROR_INDICATION_RECEIVED_FROM_RNC_ENODEB_S4_SGSN, 6). +-define(GTP2_CAUSE_IMSI_DETACH_ONLY, 7). +-define(GTP2_CAUSE_REACTIVATION_REQUESTED, 8). +-define(GTP2_CAUSE_PDN_RECONNECTION_TO_THIS_APN_DISALLOWED, 9). +-define(GTP2_CAUSE_ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP, 10). +-define(GTP2_CAUSE_PDN_CONNECTION_INACTIVITY_TIMER_EXPIRES, 11). +-define(GTP2_CAUSE_PGW_NOT_RESPONDING, 12). +-define(GTP2_CAUSE_NETWORK_FAILURE, 13). +-define(GTP2_CAUSE_QOS_PARAMETER_MISMATCH, 14). +-define(GTP2_CAUSE_REQUEST_ACCEPTED, 16). +-define(GTP2_CAUSE_REQUEST_ACCEPTED_PARTIALLY, 17). +-define(GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_NETWORK_PREFERENCE, 18). +-define(GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_SINGLE_ADDRESS_BEARER_ONLY, 19). +-define(GTP2_CAUSE_CONTEXT_NOT_FOUND, 64). +-define(GTP2_CAUSE_INVALID_MESSAGE_FORMAT, 65). +-define(GTP2_CAUSE_VERSION_NOT_SUPPORTED_BY_NEXT_PEER, 66). +-define(GTP2_CAUSE_INVALID_LENGTH, 67). +-define(GTP2_CAUSE_SERVICE_NOT_SUPPORTED, 68). +-define(GTP2_CAUSE_MANDATORY_IE_INCORRECT, 69). +-define(GTP2_CAUSE_MANDATORY_IE_MISSING, 70). +-define(GTP2_CAUSE_SYSTEM_FAILURE, 72). +-define(GTP2_CAUSE_NO_RESOURCES_AVAILABLE, 73). +-define(GTP2_CAUSE_SEMANTIC_ERROR_IN_THE_TFT_OPERATION, 74). +-define(GTP2_CAUSE_SYNTACTIC_ERROR_IN_THE_TFT_OPERATION, 75). +-define(GTP2_CAUSE_SEMANTIC_ERRORS_IN_PACKET_FILTER, 76). +-define(GTP2_CAUSE_SYNTACTIC_ERRORS_IN_PACKET_FILTER, 77). +-define(GTP2_CAUSE_MISSING_OR_UNKNOWN_APN, 78). +-define(GTP2_CAUSE_GRE_KEY_NOT_FOUND, 80). +-define(GTP2_CAUSE_RELOCATION_FAILURE, 81). +-define(GTP2_CAUSE_DENIED_IN_RAT, 82). +-define(GTP2_CAUSE_PREFERRED_PDN_TYPE_NOT_SUPPORTED, 83). +-define(GTP2_CAUSE_ALL_DYNAMIC_ADDRESSES_ARE_OCCUPIED, 84). +-define(GTP2_CAUSE_UE_CONTEXT_WITHOUT_TFT_ALREADY_ACTIVATED, 85). +-define(GTP2_CAUSE_PROTOCOL_TYPE_NOT_SUPPORTED, 86). +-define(GTP2_CAUSE_UE_NOT_RESPONDING, 87). +-define(GTP2_CAUSE_UE_REFUSES, 88). +-define(GTP2_CAUSE_SERVICE_DENIED, 89). +-define(GTP2_CAUSE_UNABLE_TO_PAGE_UE, 90). +-define(GTP2_CAUSE_NO_MEMORY_AVAILABLE, 91). +-define(GTP2_CAUSE_USER_AUTHENTICATION_FAILED, 92). +-define(GTP2_CAUSE_APN_ACCESS_DENIED___NO_SUBSCRIPTION, 93). +-define(GTP2_CAUSE_REQUEST_REJECTED, 94). +-define(GTP2_CAUSE_P_TMSI_SIGNATURE_MISMATCH, 95). +-define(GTP2_CAUSE_IMSI_IMEI_NOT_KNOWN, 96). +-define(GTP2_CAUSE_SEMANTIC_ERROR_IN_THE_TAD_OPERATION, 97). +-define(GTP2_CAUSE_SYNTACTIC_ERROR_IN_THE_TAD_OPERATION, 98). +-define(GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING, 100). +-define(GTP2_CAUSE_COLLISION_WITH_NETWORK_INITIATED_REQUEST, 101). +-define(GTP2_CAUSE_UNABLE_TO_PAGE_UE_DUE_TO_SUSPENSION, 102). +-define(GTP2_CAUSE_CONDITIONAL_IE_MISSING, 103). +-define(GTP2_CAUSE_APN_RESTRICTION_TYPE_INCOMPATIBLE_WITH_CURRENTLY_ACTIVE_PDN_CONNECTION, 104). +-define(GTP2_CAUSE_INVALID_OVERALL_LENGTH_OF_THE_TRIGGERED_RESPONSE_MESSAGE_AND_A_PIGGYBACKED_INITIAL_MESSAGE, 105). +-define(GTP2_CAUSE_DATA_FORWARDING_NOT_SUPPORTED, 106). +-define(GTP2_CAUSE_INVALID_REPLY_FROM_REMOTE_PEER, 107). +-define(GTP2_CAUSE_FALLBACK_TO_GTPV1, 108). +-define(GTP2_CAUSE_INVALID_PEER, 109). +-define(GTP2_CAUSE_TEMPORARILY_REJECTED_DUE_TO_HANDOVER_TAU_RAU_PROCEDURE_IN_PROGRESS, 110). +-define(GTP2_CAUSE_MODIFICATIONS_NOT_LIMITED_TO_S1_U_BEARERS, 111). +-define(GTP2_CAUSE_REQUEST_REJECTED_FOR_A_PMIPV6_REASON, 112). +-define(GTP2_CAUSE_APN_CONGESTION, 113). +-define(GTP2_CAUSE_BEARER_HANDLING_NOT_SUPPORTED, 114). +-define(GTP2_CAUSE_UE_ALREADY_RE_ATTACHED, 115). +-define(GTP2_CAUSE_MULTIPLE_PDN_CONNECTIONS_FOR_A_GIVEN_APN_NOT_ALLOWED, 116). +-define(GTP2_CAUSE_TARGET_ACCESS_RESTRICTED_FOR_THE_SUBSCRIBER, 117). +-define(GTP2_CAUSE_MME_SGSN_REFUSES_DUE_TO_VPLMN_POLICY, 119). +-define(GTP2_CAUSE_GTP_C_ENTITY_CONGESTION, 120). +-define(GTP2_CAUSE_LATE_OVERLAPPING_REQUEST, 121). +-define(GTP2_CAUSE_TIMED_OUT_REQUEST, 122). +-define(GTP2_CAUSE_UE_IS_TEMPORARILY_NOT_REACHABLE_DUE_TO_POWER_SAVING, 123). +-define(GTP2_CAUSE_RELOCATION_FAILURE_DUE_TO_NAS_MESSAGE_REDIRECTION, 124). +-define(GTP2_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER, 125). +-define(GTP2_CAUSE_MULTIPLE_ACCESSES_TO_A_PDN_CONNECTION_NOT_ALLOWED, 126). +-define(GTP2_CAUSE_REQUEST_REJECTED_DUE_TO_UE_CAPABILITY, 127). +-define(GTP2_CAUSE_S1_U_PATH_FAILURE, 128). +-define(GTP2_CAUSE_5GC_NOT_ALLOWED, 129). \ No newline at end of file diff --git a/src/conv.erl b/src/conv.erl new file mode 100644 index 0000000..30365cc --- /dev/null +++ b/src/conv.erl @@ -0,0 +1,53 @@ +% Conversion tools +% (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(conv). +-author('Pau Espin Pedrol <pespin(a)sysmocom.de>'). + +-include_lib("osmo_gsup/include/gsup_protocol.hrl"). +-include_lib("gtp_utils.hrl"). + +-export([cause_gtp2gsup/1]). + +-spec cause_gtp2gsup(integer()) -> integer(). + +cause_gtp2gsup(?GTP2_CAUSE_REQUEST_ACCEPTED) -> 0; +cause_gtp2gsup(?GTP2_CAUSE_IMSI_IMEI_NOT_KNOWN) -> ?GSUP_CAUSE_IMSI_UNKNOWN; +cause_gtp2gsup(?GTP2_CAUSE_INVALID_PEER) -> ?GSUP_CAUSE_ILLEGAL_MS; +cause_gtp2gsup(?GTP2_CAUSE_DENIED_IN_RAT) -> ?GSUP_CAUSE_GPRS_NOTALLOWED; +cause_gtp2gsup(?GTP2_CAUSE_NETWORK_FAILURE) -> ?GSUP_CAUSE_NET_FAIL; +cause_gtp2gsup(?GTP2_CAUSE_APN_CONGESTION) -> ?GSUP_CAUSE_CONGESTION; +cause_gtp2gsup(?GTP2_CAUSE_GTP_C_ENTITY_CONGESTION) -> ?GSUP_CAUSE_CONGESTION; +cause_gtp2gsup(?GTP2_CAUSE_USER_AUTHENTICATION_FAILED) -> ?GSUP_CAUSE_GSM_AUTH_UNACCEPT; +cause_gtp2gsup(?GTP2_CAUSE_MANDATORY_IE_INCORRECT) -> ?GSUP_CAUSE_INV_MAND_INFO; +cause_gtp2gsup(?GTP2_CAUSE_MANDATORY_IE_MISSING) -> ?GSUP_CAUSE_INV_MAND_INFO; +cause_gtp2gsup(_) -> ?GSUP_CAUSE_PROTO_ERR_UNSPEC. diff --git a/src/epdg_gtpc_s2b.erl b/src/epdg_gtpc_s2b.erl index fc41351..7e3dd6e 100644 --- a/src/epdg_gtpc_s2b.erl +++ b/src/epdg_gtpc_s2b.erl @@ -48,7 +48,7 @@ %% gen_server Function Exports -export([init/1, handle_call/3, handle_cast/2, handle_info/2]). -export([code_change/3]). --export([create_session_req/1]). +-export([create_session_req/1, delete_session_req/1]). %% Application Definitions -define(SERVER, ?MODULE). @@ -139,13 +139,28 @@ create_session_req(Imsi) -> gen_server:call(?SERVER, {gtpc_create_session_req, {Imsi}}). +delete_session_req(Imsi) -> + gen_server:call(?SERVER, {gtpc_delete_session_req, {Imsi}}). + handle_call({gtpc_create_session_req, {Imsi}}, {Pid, _Tag} = _From, State0) -> {Sess0, State1} = find_or_new_gtp_session(Imsi, Pid, State0), Req = gen_create_session_request(Sess0, State1), %TODO: increment State.seq_no. tx_gtp(Req, State1), lager:debug("Waiting for CreateSessionResponse~n", []), - {reply, ok, State1}. + {reply, ok, State1}; + +handle_call({gtpc_delete_session_req, {Imsi}}, _From, State) -> + Sess = find_gtp_session_by_imsi(Imsi, State), + case Sess of + #gtp_session{imsi = Imsi} -> + Req = gen_delete_session_request(Sess, State), + %TODO: increment State.seq_no. + tx_gtp(Req, State), + {reply, ok, State}; + undefined -> + {reply, {error, imsi_unknown}, State} + end. %% @callback gen_server handle_cast(stop, State) -> @@ -276,6 +291,18 @@ {noreply, State1} end; +rx_gtp(Resp = #gtp{version = v2, type = delete_session_response}, State0) -> + Sess = find_gtp_session_by_local_teic(Resp#gtp.tei, State0), + case Sess of + undefined -> + lager:error("Rx unknown TEI ~p: ~p~n", [Resp#gtp.tei, Resp]), + {noreply, State0}; + Sess -> + State1 = delete_gtp_session(Sess, State0), + ue_fsm:received_gtpc_delete_session_response(Sess#gtp_session.pid, Resp), + {noreply, State1} + end; + rx_gtp(Req = #gtp{version = v2, type = delete_bearer_request}, State) -> Sess = find_gtp_session_by_local_teic(Req#gtp.tei, State), case Sess of @@ -340,6 +367,22 @@ ], #gtp{version = v2, type = create_session_request, tei = 0, seq_no = SeqNo, ie = IEs}. +%% 7.2.9 Delete Session Request +gen_delete_session_request(#gtp_session{remote_control_tei = RemoteCtlTEI, + bearer = Bearer}, + #gtp_state{laddr = LocalAddr, + seq_no = SeqNo}) -> + IEs = [#v2_eps_bearer_id{eps_bearer_id = Bearer#gtp_bearer.ebi}, + #v2_fully_qualified_tunnel_endpoint_identifier{ + instance = Bearer#gtp_bearer.ebi, + interface_type = 30, %% "S2b ePDG GTP-C" + key = Bearer#gtp_bearer.local_data_tei, + ipv4 = gtp_utils:ip_to_bin(LocalAddr) + } + ], + #gtp{version = v2, type = delete_session_request, tei = RemoteCtlTEI, seq_no = SeqNo, ie = IEs}. + + gen_delete_bearer_response(Req = #gtp{version = v2, type = delete_bearer_request}, Sess = #gtp_session{remote_control_tei = RemoteCtlTEI}, GtpCause, diff --git a/src/gsup_server.erl b/src/gsup_server.erl index 30e8864..cebcc0f 100644 --- a/src/gsup_server.erl +++ b/src/gsup_server.erl @@ -62,7 +62,7 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2]). -export([code_change/3, terminate/2]). --export([auth_response/2, lu_response/2, tunnel_response/2]). +-export([auth_response/2, lu_response/2, tunnel_response/2, purge_ms_response/2]). % TODO: -spec dia_sip2gsup('SIP-Auth-Data-Item'()) -> #'GSUPAuthTuple'{}. dia_sip2gsup(#'SIP-Auth-Data-Item'{'SIP-Authenticate' = [Authenticate], 'SIP-Authorization' = [Authorization], @@ -182,6 +182,25 @@ tx_gsup(Socket, Resp), {noreply, State}; +handle_cast({purge_ms_response, {Imsi, Result}}, State0) -> + lager:info("purge_ms_response for ~p: ~p~n", [Imsi, Result]), + Socket = State0#gsups_state.socket, + case Result of + ok -> + Resp = #{message_type => purge_ms_res, + imsi => Imsi, + freeze_p_tmsi => true + }; + {error, GsupCause} -> + Resp = #{message_type => purge_ms_err, + imsi => Imsi, + cause => GsupCause + } + end, + tx_gsup(Socket, Resp), + State1 = delete_gsups_ue(Imsi, State0), + {noreply, State1}; + handle_cast(Info, S) -> error_logger:error_report(["unknown handle_cast", {module, ?MODULE}, {info, Info}, {state, S}]), {noreply, S}. @@ -269,6 +288,31 @@ end, {noreply, State}; +% Purge MS / trigger the delete of session to the PGW +handle_info({ipa, Socket, ?IPAC_PROTO_EXT_GSUP, GsupMsgRx = #{message_type := purge_ms_req, imsi := Imsi}}, State) -> + lager:info("GSUP: Rx ~p~n", [GsupMsgRx]), + UE = find_gsups_ue_by_imsi(Imsi, State), + case UE of + #gsups_ue{imsi = Imsi} -> + case ue_fsm:purge_ms_request(UE#gsups_ue.pid) of + ok -> ok; + _ -> Resp = #{message_type => purge_ms_err, + imsi => Imsi, + message_class => 5, + cause => ?GSUP_CAUSE_NET_FAIL + }, + tx_gsup(Socket, Resp) + end; + undefined -> + Resp = #{message_type => purge_ms_err, + imsi => Imsi, + message_class => 5, + cause => ?GSUP_CAUSE_IMSI_UNKNOWN + }, + tx_gsup(Socket, Resp) + end, + {noreply, State}; + handle_info(Info, S) -> error_logger:error_report(["unknown handle_info", {module, ?MODULE}, {info, Info}, {state, S}]), {noreply, S}. @@ -291,6 +335,10 @@ lager:info("tunnel_response(~p): ~p~n", [Imsi, Result]), gen_server:cast(?SERVER, {tunnel_response, {Imsi, Result}}). +purge_ms_response(Imsi, Result) -> + lager:info("purge_ms_response(~p): ~p~n", [Imsi, Result]), + gen_server:cast(?SERVER, {purge_ms_response, {Imsi, Result}}). + %% ------------------------------------------------------------------ %% Internal Function Definitions %% ------------------------------------------------------------------ @@ -322,4 +370,8 @@ {UE, State}; undefined -> new_gsups_ue(Imsi, State) - end. \ No newline at end of file + end. + +delete_gsups_ue(Imsi, State) -> + SetRemoved = sets:del_element(Imsi, State#gsups_state.ues), + State#gsups_state{ues = SetRemoved}. \ No newline at end of file diff --git a/src/gtp_utils.erl b/src/gtp_utils.erl index 85f69ef..eb0a23a 100644 --- a/src/gtp_utils.erl +++ b/src/gtp_utils.erl @@ -35,7 +35,7 @@ -module(gtp_utils). -author('Alexander Couzens <lynxis(a)fe80.eu>'). --export([ip_to_bin/1, plmn_to_bin/3]). +-export([ip_to_bin/1, plmn_to_bin/3, enum_v2_cause/1]). % ergw_aaa/src/ergw_aaa_3gpp_dict.erl % under GPLv2+ @@ -52,3 +52,84 @@ MCC = iolist_to_binary(io_lib:format("~3..0b", [CC])), MNC = iolist_to_binary(io_lib:format("~*..0b", [NCSize, NC])), {MCC, MNC}. + +enum_v2_cause(reserved) -> 1; +enum_v2_cause(local_detach) -> 2; +enum_v2_cause(complete_detach) -> 3; +enum_v2_cause(rat_changed_from_3gpp_to_non_3gpp) -> 4; +enum_v2_cause(isr_deactivation) -> 5; +enum_v2_cause(error_indication_received_from_rnc_enodeb_s4_sgsn) -> 6; +enum_v2_cause(imsi_detach_only) -> 7; +enum_v2_cause(reactivation_requested) -> 8; +enum_v2_cause(pdn_reconnection_to_this_apn_disallowed) -> 9; +enum_v2_cause(access_changed_from_non_3gpp_to_3gpp) -> 10; +enum_v2_cause(pdn_connection_inactivity_timer_expires) -> 11; +enum_v2_cause(pgw_not_responding) -> 12; +enum_v2_cause(network_failure) -> 13; +enum_v2_cause(qos_parameter_mismatch) -> 14; +enum_v2_cause(request_accepted) -> 16; +enum_v2_cause(request_accepted_partially) -> 17; +enum_v2_cause(new_pdn_type_due_to_network_preference) -> 18; +enum_v2_cause(new_pdn_type_due_to_single_address_bearer_only) -> 19; +enum_v2_cause(context_not_found) -> 64; +enum_v2_cause(invalid_message_format) -> 65; +enum_v2_cause(version_not_supported_by_next_peer) -> 66; +enum_v2_cause(invalid_length) -> 67; +enum_v2_cause(service_not_supported) -> 68; +enum_v2_cause(mandatory_ie_incorrect) -> 69; +enum_v2_cause(mandatory_ie_missing) -> 70; +enum_v2_cause(system_failure) -> 72; +enum_v2_cause(no_resources_available) -> 73; +enum_v2_cause(semantic_error_in_the_tft_operation) -> 74; +enum_v2_cause(syntactic_error_in_the_tft_operation) -> 75; +enum_v2_cause(semantic_errors_in_packet_filter) -> 76; +enum_v2_cause(syntactic_errors_in_packet_filter) -> 77; +enum_v2_cause(missing_or_unknown_apn) -> 78; +enum_v2_cause(gre_key_not_found) -> 80; +enum_v2_cause(relocation_failure) -> 81; +enum_v2_cause(denied_in_rat) -> 82; +enum_v2_cause(preferred_pdn_type_not_supported) -> 83; +enum_v2_cause(all_dynamic_addresses_are_occupied) -> 84; +enum_v2_cause(ue_context_without_tft_already_activated) -> 85; +enum_v2_cause(protocol_type_not_supported) -> 86; +enum_v2_cause(ue_not_responding) -> 87; +enum_v2_cause(ue_refuses) -> 88; +enum_v2_cause(service_denied) -> 89; +enum_v2_cause(unable_to_page_ue) -> 90; +enum_v2_cause(no_memory_available) -> 91; +enum_v2_cause(user_authentication_failed) -> 92; +enum_v2_cause(apn_access_denied___no_subscription) -> 93; +enum_v2_cause(request_rejected) -> 94; +enum_v2_cause(p_tmsi_signature_mismatch) -> 95; +enum_v2_cause(imsi_imei_not_known) -> 96; +enum_v2_cause(semantic_error_in_the_tad_operation) -> 97; +enum_v2_cause(syntactic_error_in_the_tad_operation) -> 98; +enum_v2_cause(remote_peer_not_responding) -> 100; +enum_v2_cause(collision_with_network_initiated_request) -> 101; +enum_v2_cause(unable_to_page_ue_due_to_suspension) -> 102; +enum_v2_cause(conditional_ie_missing) -> 103; +enum_v2_cause(apn_restriction_type_incompatible_with_currently_active_pdn_connection) -> 104; +enum_v2_cause(invalid_overall_length_of_the_triggered_response_message_and_a_piggybacked_initial_message) -> 105; +enum_v2_cause(data_forwarding_not_supported) -> 106; +enum_v2_cause(invalid_reply_from_remote_peer) -> 107; +enum_v2_cause(fallback_to_gtpv1) -> 108; +enum_v2_cause(invalid_peer) -> 109; +enum_v2_cause(temporarily_rejected_due_to_handover_tau_rau_procedure_in_progress) -> 110; +enum_v2_cause(modifications_not_limited_to_s1_u_bearers) -> 111; +enum_v2_cause(request_rejected_for_a_pmipv6_reason) -> 112; +enum_v2_cause(apn_congestion) -> 113; +enum_v2_cause(bearer_handling_not_supported) -> 114; +enum_v2_cause(ue_already_re_attached) -> 115; +enum_v2_cause(multiple_pdn_connections_for_a_given_apn_not_allowed) -> 116; +enum_v2_cause(target_access_restricted_for_the_subscriber) -> 117; +enum_v2_cause(mme_sgsn_refuses_due_to_vplmn_policy) -> 119; +enum_v2_cause(gtp_c_entity_congestion) -> 120; +enum_v2_cause(late_overlapping_request) -> 121; +enum_v2_cause(timed_out_request) -> 122; +enum_v2_cause(ue_is_temporarily_not_reachable_due_to_power_saving) -> 123; +enum_v2_cause(relocation_failure_due_to_nas_message_redirection) -> 124; +enum_v2_cause(ue_not_authorised_by_ocs_or_external_aaa_server) -> 125; +enum_v2_cause(multiple_accesses_to_a_pdn_connection_not_allowed) -> 126; +enum_v2_cause(request_rejected_due_to_ue_capability) -> 127; +enum_v2_cause(s1_u_path_failure) -> 128; +enum_v2_cause('5gc_not_allowed') -> 129. diff --git a/src/ue_fsm.erl b/src/ue_fsm.erl index c0b8872..f17dfdc 100644 --- a/src/ue_fsm.erl +++ b/src/ue_fsm.erl @@ -34,10 +34,14 @@ -behaviour(gen_statem). -define(NAME, ue_fsm). +-include_lib("osmo_gsup/include/gsup_protocol.hrl"). +-include_lib("gtplib/include/gtp_packet.hrl"). + -export([start_link/1]). -export([init/1,callback_mode/0,terminate/3]). --export([auth_request/1, lu_request/1, tunnel_request/1, received_gtpc_create_session_response/2]). --export([state_new/3,state_authenticated/3]). +-export([auth_request/1, lu_request/1, tunnel_request/1, purge_ms_request/1]). +-export([received_gtpc_create_session_response/2, received_gtpc_delete_session_response/2]). +-export([state_new/3,state_authenticated/3, state_wait_delete_session_resp/3]). -record(ue_fsm_data, { imsi @@ -75,6 +79,15 @@ {error, Err} end. +purge_ms_request(Pid) -> + lager:info("ue_fsm purge_ms_request~n", []), + try + gen_statem:call(Pid, purge_ms_request) + catch + exit:Err -> + {error, Err} + end. + received_gtpc_create_session_response(Pid, Msg) -> lager:info("ue_fsm received_gtpc_create_session_response ~p~n", [Msg]), try @@ -84,6 +97,23 @@ {error, Err} end. +received_gtpc_delete_session_response(Pid, Msg) -> + lager:info("ue_fsm received_gtpc_delete_session_response ~p~n", [Msg]), + try + gen_statem:call(Pid, {received_gtpc_delete_session_response, Msg}) + 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}, @@ -105,7 +135,11 @@ {next_state, state_authenticated, Data, [{reply,From,ok}]}; {error, Err} -> {stop_and_reply, Err, Data, [{reply,From,{error,Err}}]} - end. + end; + +state_new({call, From}, purge_ms_request, Data) -> + lager:info("ue_fsm state_new event=purge_ms_request, ~p~n", [Data]), + {stop_and_reply, purge_ms_request, Data, [{reply,From,ok}]}. state_authenticated({call, From}, lu_request, Data) -> lager:info("ue_fsm state_authenticated event=lu_request, ~p~n", [Data]), @@ -128,10 +162,33 @@ gsup_server:tunnel_response(Data#ue_fsm_data.imsi, Result), {keep_state, Data, [{reply,From,ok}]}; +state_authenticated({call, From}, purge_ms_request, Data) -> + lager:info("ue_fsm state_authenticated event=purge_ms_request, ~p~n", [Data]), + case epdg_gtpc_s2b:delete_session_req(Data#ue_fsm_data.imsi) of + ok -> {next_state, state_wait_delete_session_resp, Data, [{reply,From,ok}]}; + {error, Err} -> {keep_state, Data, [{reply,From,{error, Err}}]} + end; + state_authenticated({call, From}, _Whatever, Data) -> lager:error("ue_fsm state_authenticated: Unexpected call event, ~p~n", [Data]), {keep_state, Data, [{reply,From,ok}]}; state_authenticated(cast, _Whatever, Data) -> lager:error("ue_fsm state_authenticated: Unexpected cast event, ~p~n", [Data]), - {keep_state, Data}. \ No newline at end of file + {keep_state, Data}. + +state_wait_delete_session_resp({call, From}, {received_gtpc_delete_session_response, _Resp = #gtp{version = v2, type = delete_session_response, ie = IEs}}, Data) -> + lager:info("ue_fsm state_wait_delete_session_resp event=received_gtpc_delete_session_response, ~p~n", [Data]), + #{{v2_cause,0} := CauseIE} = IEs, + GtpCause = gtp_utils:enum_v2_cause(CauseIE#v2_cause.v2_cause), + GsupCause = conv:cause_gtp2gsup(GtpCause), + lager:debug("Cause: GTP_atom=~p -> GTP_int=~p -> GSUP_int=~p~n", [CauseIE#v2_cause.v2_cause, GtpCause, GsupCause]), + case GsupCause of + 0 -> gsup_server:purge_ms_response(Data#ue_fsm_data.imsi, ok); + _ -> gsup_server:purge_ms_response(Data#ue_fsm_data.imsi, {error, GsupCause}) + end, + {keep_state, Data, [{reply,From,ok}]}; + +state_wait_delete_session_resp({call, From}, Event, Data) -> + lager:error("ue_fsm state_wait_delete_session_resp: Unexpected call event ~p, ~p~n", [Event, Data]), + {keep_state, Data, [{reply,From,{error,unexpected_event}}]}. -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35676?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: I2e922f76c2fa601c5f61fa23d6df5fb62c3e133d Gerrit-Change-Number: 35676 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 year, 5 months
1
0
0
0
[L] Change in ...osmo-epdg[master]: Implement UE-initiated Detach
by pespin
pespin has posted comments on this change. (
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35676?usp=email
) Change subject: Implement UE-initiated Detach ...................................................................... Patch Set 1: Code-Review+2 -- To view, visit
https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/35676?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: I2e922f76c2fa601c5f61fa23d6df5fb62c3e133d Gerrit-Change-Number: 35676 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Comment-Date: Thu, 25 Jan 2024 14:44:48 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 year, 5 months
1
0
0
0
← Newer
1
...
34
35
36
37
38
39
40
...
156
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
Results per page:
10
25
50
100
200