clufn has uploaded this change for review. ( https://gerrit.osmocom.org/c/erlang/osmo-epdg/+/40277?usp=email )
Change subject: Enable the use of an UE requested IP type and address to be used for gtpv2 PDN Address Allocation ......................................................................
Enable the use of an UE requested IP type and address to be used for gtpv2 PDN Address Allocation
Change-Id: If0c77b1e366df36439d3a1b72030d831dd1b3a05 --- M src/conv.erl M src/epdg_gtpc_s2b.erl M src/epdg_ue_fsm.erl M src/gsup_server.erl 4 files changed, 43 insertions(+), 22 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-epdg refs/changes/77/40277/1
diff --git a/src/conv.erl b/src/conv.erl index 5832c64..d2a54ab 100644 --- a/src/conv.erl +++ b/src/conv.erl @@ -41,7 +41,7 @@ -export([ip_to_bin/1, bin_to_ip/1]). -export([cause_gtp2gsup/1]). -export([dia_rc_success/1, dia_rc_to_gsup_cause/1]). --export([gtp2_paa_to_epdg_eua/1, epdg_eua_to_gsup_pdp_address/1]). +-export([gtp2_paa_to_epdg_eua/1, pdp_address_to_gtp2_paa/2, epdg_eua_to_gsup_pdp_address/1]). -export([nai_to_imsi/1]).
% ergw_aaa/src/ergw_aaa_3gpp_dict.erl @@ -62,6 +62,9 @@ bin_to_ip({_, _, _, _, _, _, _, _} = IP) -> IP.
+%% Add "IPv6 Prefix Length" to PAA (3GPP TS 29.274 Table 8.14). +add_v6_prefix_len_byte(<< IPv6:16/binary >>) -> << 8, IPv6/binary >>. + %% Remove "IPv6 Prefix Length" from PAA (3GPP TS 29.274 Table 8.14). remove_v6_prefix_len_byte(<<_:8, Rest/binary>>) -> Rest.
@@ -129,6 +132,13 @@ ipv4 = get_4_from_v4v6(Addr), ipv6 = get_6_from_v4v6(Addr)}.
+pdp_address_to_gtp2_paa(?GTP_PDP_ADDR_TYPE_NR_IPv4, Address) -> + #v2_pdn_address_allocation{type = ipv4, address = maps:get(ipv4,Address)}; +pdp_address_to_gtp2_paa(?GTP_PDP_ADDR_TYPE_NR_IPv6, Address) -> + #v2_pdn_address_allocation{type = ipv6, address = add_v6_prefix_len_byte(maps:get(ipv6,Address))}; +pdp_address_to_gtp2_paa(?GTP_PDP_ADDR_TYPE_NR_IPv4v6, Address) -> + #v2_pdn_address_allocation{type = ipv4v6, address = get_v4v6(maps:get(ipv4,Address),maps:get(ipv6,Address))}. + epdg_eua_to_gsup_pdp_address(#epdg_eua{type_nr = ?GTP_PDP_ADDR_TYPE_NR_IPv4, ipv4 = Addr}) -> #{pdp_type_org => 1, pdp_type_nr => ?GTP_PDP_ADDR_TYPE_NR_IPv4, diff --git a/src/epdg_gtpc_s2b.erl b/src/epdg_gtpc_s2b.erl index 4b88be3..d4d2b71 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/4, delete_session_req/1]). +-export([create_session_req/5, delete_session_req/1]).
%% Application Definitions -define(SERVER, ?MODULE). @@ -144,13 +144,13 @@ lager:error("GTPv2C UDP socket open error: ~w~n", [Reason]) end.
-create_session_req(Imsi, Apn, APCO, PGWAddrCandidateList) -> - gen_server:call(?SERVER, {gtpc_create_session_req, {Imsi, Apn, APCO, PGWAddrCandidateList}}). +create_session_req(Imsi, Apn, APCO, Paa, PGWAddrCandidateList) -> + gen_server:call(?SERVER, {gtpc_create_session_req, {Imsi, Apn, APCO, Paa, PGWAddrCandidateList}}).
delete_session_req(Imsi) -> gen_server:call(?SERVER, {gtpc_delete_session_req, {Imsi}}).
-handle_call({gtpc_create_session_req, {Imsi, Apn, APCO, PGWAddrCandidateList}}, {Pid, _Tag} = _From, State0) -> +handle_call({gtpc_create_session_req, {Imsi, Apn, APCO, Paa, PGWAddrCandidateList}}, {Pid, _Tag} = _From, State0) -> RemoteAddrStr = pick_gtpc_remote_address(PGWAddrCandidateList, State0), lager:debug("Selected PGW Remote Address ~p~n", [RemoteAddrStr]), {ok, RemoteAddrInet} = inet_parse:address(RemoteAddrStr), @@ -160,7 +160,7 @@ raddr_str = RemoteAddrInet, raddr = RemoteAddrInet}, State0), - Req = gen_create_session_request(Sess0, APCO, State1), + Req = gen_create_session_request(Sess0, APCO, Paa, State1), tx_gtp(Req, State1), State2 = inc_seq_no(State1), lager:debug("Waiting for CreateSessionResponse~n", []), @@ -514,6 +514,7 @@ apn = Apn, local_control_tei = LocalCtlTEI} = Sess, APCO, + Paa, #gtp_state{laddr = LocalAddr, laddr_gtpu = LocalAddrGtpu, restart_counter = RCnt, @@ -548,7 +549,7 @@ }, #v2_access_point_name{instance = 0, apn = [Apn]}, #v2_selection_mode{mode = 0}, - #v2_pdn_address_allocation{type = ipv4, address = <<0,0,0,0>>}, + Paa, %% v2_pdn_address_allocation #v2_bearer_context{group = BearersIE}, #v2_recovery{restart_counter = RCnt}, #v2_additional_protocol_configuration_options{instance = 0, config = APCO_decoded} diff --git a/src/epdg_ue_fsm.erl b/src/epdg_ue_fsm.erl index 2e4f417..220bc5e 100644 --- a/src/epdg_ue_fsm.erl +++ b/src/epdg_ue_fsm.erl @@ -66,6 +66,7 @@
-record(ue_fsm_data, { imsi, + paa, apn = "internet" :: string(), pgw_rem_addr_list = [] :: list(), tun_pdp_ctx :: #epdg_tun_pdp_ctx{}, @@ -96,10 +97,10 @@ {error, Err} end.
-auth_request(Pid, {PdpTypeNr, Apn, EAP}) -> +auth_request(Pid, {PdpTypeNr, PdpAddress, Apn, EAP}) -> lager:info("ue_fsm auth_request~n", []), try - gen_statem:call(Pid, {auth_request, PdpTypeNr, Apn, EAP}) + gen_statem:call(Pid, {auth_request, PdpTypeNr, PdpAddress, Apn, EAP}) catch exit:Err -> {error, Err} @@ -227,7 +228,7 @@ %% Internal helpers %% ------------------------------------------------------------------
-ev_handle({call, From}, {auth_request, PdpTypeNr, Apn, EAP}, Data) -> +ev_handle({call, From}, {auth_request, PdpTypeNr, PdpAddress, Apn, EAP}, Data) -> epdg_diameter_swm:tx_der_auth_request(Data#ue_fsm_data.imsi, PdpTypeNr, Apn, EAP), {next_state, state_wait_auth_resp, Data, [{reply,From,ok}]}.
@@ -258,9 +259,10 @@ state_new(enter, _OldState, Data) -> {keep_state, Data};
-state_new({call, _From} = EvType, {auth_request, PdpTypeNr, Apn, EAP} = EvContent, Data) -> - lager:info("ue_fsm state_new event=auth_request {~p, ~p, ~p}, ~p~n", [PdpTypeNr, Apn, EAP, Data]), - ev_handle(EvType, EvContent, Data); +state_new({call, _From} = EvType, {auth_request, PdpTypeNr, PdpAddress, Apn, EAP} = EvContent, Data) -> + lager:info("ue_fsm state_new event=auth_request {~p, ~p, ~p}, ~p~n", [PdpTypeNr, PdpAddress, Apn, EAP, Data]), + Data1 = Data#ue_fsm_data{paa = conv:pdp_address_to_gtp2_paa(PdpTypeNr, PdpAddress), apn = Apn}, + ev_handle(EvType, EvContent, Data1);
state_new({call, From}, purge_ms_request, Data) -> lager:info("ue_fsm state_new event=purge_ms_request, ~p~n", [Data]), @@ -300,8 +302,8 @@ state_authenticating(enter, _OldState, Data) -> {keep_state, Data};
-state_authenticating({call, _From} = EvType, {auth_request, PdpTypeNr, Apn, EAP} = EvContent, Data) -> - lager:info("ue_fsm state_authenticating event=auth_request {~p, ~p, ~p}, ~p~n", [PdpTypeNr, Apn, EAP, Data]), +state_authenticating({call, _From} = EvType, {auth_request, PdpTypeNr, PdpAddress, Apn, EAP} = EvContent, Data) -> + lager:info("ue_fsm state_authenticating event=auth_request {~p, ~p, ~p}, ~p~n", [PdpTypeNr, PdpAddress, Apn, EAP, Data]), ev_handle(EvType, EvContent, Data);
state_authenticating({call, From}, lu_request, Data) -> @@ -339,8 +341,8 @@ state_authenticated(enter, _OldState, Data) -> {keep_state, Data};
-state_authenticated({call, _From}, {auth_request, PdpTypeNr, Apn, EAP}, Data) -> - lager:info("ue_fsm state_authenticated event=auth_request {~p, ~p, ~p}, ~p~n", [PdpTypeNr, Apn, EAP, Data]), +state_authenticated({call, _From}, {auth_request, PdpTypeNr, PdpAddress, Apn, EAP}, Data) -> + lager:info("ue_fsm state_authenticated event=auth_request {~p, ~p, ~p}, ~p~n", [PdpTypeNr, PdpAddress, Apn, EAP, Data]), {next_state, state_new, Data, [postpone]};
state_authenticated({call, From}, {tunnel_request, PCO}, Data) -> @@ -348,6 +350,7 @@ epdg_gtpc_s2b:create_session_req(Data#ue_fsm_data.imsi, Data#ue_fsm_data.apn, PCO, + Data#ue_fsm_data.paa, Data#ue_fsm_data.pgw_rem_addr_list), {next_state, state_wait_create_session_resp, Data, [{reply,From,ok}]};
@@ -437,8 +440,8 @@ state_active(enter, _OldState, Data) -> {keep_state, Data};
-state_active({call, _From}, {auth_request, PdpTypeNr, Apn, EAP}, Data) -> - lager:info("ue_fsm state_active event=auth_request {~p, ~p, ~p}, ~p~n", [PdpTypeNr, Apn, EAP, Data]), +state_active({call, _From}, {auth_request, PdpTypeNr, PdpAddress, Apn, EAP}, Data) -> + lager:info("ue_fsm state_active event=auth_request {~p, ~p, ~p}, ~p~n", [PdpTypeNr, PdpAddress, Apn, EAP, Data]), gtp_u_tun:delete_pdp_context(Data#ue_fsm_data.tun_pdp_ctx), Data1 = Data#ue_fsm_data{tun_pdp_ctx = undefined}, {next_state, state_new, Data1, [postpone]}; diff --git a/src/gsup_server.erl b/src/gsup_server.erl index c5d3738..c4c28cf 100644 --- a/src/gsup_server.erl +++ b/src/gsup_server.erl @@ -296,13 +296,20 @@ case maps:find(pdp_info_list, GsupMsgRx) of {ok, [PdpInfo]} -> #{pdp_context_id := _PDPCtxId, - pdp_address := #{address := #{}, + pdp_address := #{address := PdpAddress, pdp_type_nr := PdpTypeNr, pdp_type_org := 241}, access_point_name := Apn - } = PdpInfo; + } = PdpInfo, + case maps:is_key(ipv4,PdpAddress) or maps:is_key(ipv6,PdpAddress) of + true -> ok; %% Address received so do nothing + false -> %% No address received from strongswan, use a default value + PdpTypeNr = ?GTP_PDP_ADDR_TYPE_NR_IPv4, + PdpAddress = #{ipv4 => <<0,0,0,0>>} + end; error -> % Use some sane defaults: PdpTypeNr = ?GTP_PDP_ADDR_TYPE_NR_IPv4, + PdpAddress = #{ipv4 => <<0,0,0,0>>}, Apn = "*" end, EAP = parse_eap(GsupMsgRx), @@ -310,7 +317,7 @@ undefined -> {ok, Pid} = epdg_ue_fsm:start(Imsi); Pid -> Pid end, - case epdg_ue_fsm:auth_request(Pid, {PdpTypeNr, Apn, EAP}) of + case epdg_ue_fsm:auth_request(Pid, {PdpTypeNr, PdpAddress, Apn, EAP}) of ok -> ok; {error, Err} -> lager:error("Auth Req for Imsi ~p failed: ~p~n", [Imsi, Err]),