diff options
Diffstat (limited to 'lib/compiler/test/inline_SUITE_data/bsdecode.erl')
-rw-r--r-- | lib/compiler/test/inline_SUITE_data/bsdecode.erl | 1188 |
1 files changed, 1188 insertions, 0 deletions
diff --git a/lib/compiler/test/inline_SUITE_data/bsdecode.erl b/lib/compiler/test/inline_SUITE_data/bsdecode.erl new file mode 100644 index 0000000000..ae134ad02e --- /dev/null +++ b/lib/compiler/test/inline_SUITE_data/bsdecode.erl @@ -0,0 +1,1188 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(bsdecode). +-export([?MODULE/0]). + +-record(protocolErrors, {invalidManIE = false, + outOfSequence = false, + incorrectOptIE = false}). + +-record(mvsT_msisdn, {value}). + + +-record(mvsgT_pdpAddressType, {pdpTypeNbr, + address}). + +-record(mvsgT_ipAddress, {version, + a1, + a2, + a3, + a4, + a5, + a6, + a7, + a8}). + +-record(mvsgT_imsi, {value}). + +-record(mvsgT_tid, {imsi, + nsapi}). + +-record(sesT_qualityOfServiceV0, {delayClass, + reliabilityClass, + peakThroughput, + precedenceClass, + meanThroughput}). + +-record(sesT_deleteReqV0, {tid}). + +-record(sesT_deleteResV0, {tid, + cause}). + +-record(sesT_createReqV0, {tid, + tidRaw, + qos, + recovery, + selMode, + flowLblData, + flowLblSig, + endUserAdd, + accPointName, + protConOpt, + sgsnAddSig, + sgsnAddUser, + msisdn}). + +-record(sesT_updateReqV0, {tid, + tidRaw, + qos, + recovery, + flowLblData, + flowLblSig, + sgsnAddSig, + sgsnAddUser}). + +-record(masT_ipcpData, {type, + ipAddress, + rawMessage}). + +-record(masT_ipcp, {exists, + code, + id, + ipcpList}). + +-record(masT_pap, {exists, + code, + id, + username, + password}). + +-record(masT_chap, {code, + id, + value, + name}). + +-record(masT_protocolConfigOptions, {chap, + pap, + ipcp}). + +?MODULE() -> + Res = test(), + {Res,Res =:= + {ok,{sesT_createReqV0,{mvsgT_tid,{mvsgT_imsi,<<81,67,101,7,0,0,0,240>>},6}, + [81,67,101,7,0,0,0,96], + {sesT_qualityOfServiceV0,1,4,9,2,18},0, + subscribed,0,0,{mvsgT_pdpAddressType,ietf_ipv4,[]}, + [<<97,112,110,48,49,51,97>>,<<101,114,105,99,115,115,111,110>>,<<115,101>>], + {masT_protocolConfigOptions,[], + {masT_pap,true,1,5,[117,115,101,114,53],[112,97,115,115,53]},[]}, + {mvsgT_ipAddress,ipv4,172,28,12,1,0,0,0,0}, + {mvsgT_ipAddress,ipv4,172,28,12,3,0,0,0,0}, + {mvsT_msisdn,<<145,148,113,129,0,0,0,0>>}},1}}. + +test() -> + Pdu = <<30, + 16, + 0, + 90, + 0, + 1, + 0, + 0, + 255, + 255, + 255, + 255, + 81, + 67, + 101, + 7, + 0, + 0, + 0, + 96, + 6, + 12, + 146, + 18, + 14, + 0, + 15, + 252, + 16, + 0, + 0, + 17, + 0, + 0, + 128, + 0, + 2, + 241, + 33, + 131, + 0, + 20, + 7, + 97, + 112, + 110, + 48, + 49, + 51, + 97, + 8, + 101, + 114, + 105, + 99, + 115, + 115, + 111, + 110, + 2, + 115, + 101, + 132, + 0, + 20, + 128, + 192, + 35, + 16, + 1, + 5, + 0, + 16, + 5, + 117, + 115, + 101, + 114, + 53, + 5, + 112, + 97, + 115, + 115, + 53, + 133, + 0, + 4, + 172, + 28, + 12, + 1, + 133, + 0, + 4, + 172, + 28, + 12, + 3, + 134, + 0, + 8, + 145, + 148, + 113, + 129, + 0, + 0, + 0, + 0>>, + decode_v0_opt(10,Pdu). + +decode_v0_opt(0,Pdu) -> + decode_gtpc_msg(Pdu); +decode_v0_opt(N,Pdu) -> + decode_gtpc_msg(Pdu), + decode_v0_opt(N - 1,Pdu). + +decode_gtpc_msg(<<0:3, + _:4, + 0:1, + 16:8, + _Length:16, + SequenceNumber:16, + _FlowLabel:16, + _SNDCP_N_PDU_Number:8, + _:3/binary-unit:8, + TID:8/binary-unit:8, + InformationElements/binary>>) -> + Errors = #protocolErrors{}, + {ok,TID2} = tid_internal_storage(TID,[]), + EmptyCreateReq = #sesT_createReqV0{tid = TID2, + tidRaw = binary_to_list(TID)}, + case catch decode_ie_create(InformationElements,0,Errors,EmptyCreateReq) of + {ok,CreateReq} -> + {ok,CreateReq,SequenceNumber}; + {fault,Cause,CreateReq} -> + {fault,Cause,CreateReq,SequenceNumber}; + {'EXIT',_Reason} -> + {fault,193,EmptyCreateReq,SequenceNumber} + end; +decode_gtpc_msg(<<0:3, + _:4, + 0:1, + 18:8, + _Length:16, + SequenceNumber:16, + _FlowLabel:16, + _SNDCP_N_PDU_Number:8, + _:3/binary-unit:8, + TID:8/binary-unit:8, + InformationElements/binary>>) -> + io:format("hej",[]), + Errors = #protocolErrors{}, + {ok,TID2} = tid_internal_storage(TID,[]), + EmptyUpdateReq = #sesT_updateReqV0{tid = TID2, + tidRaw = binary_to_list(TID)}, + case catch decode_ie_update(InformationElements,0,Errors,EmptyUpdateReq) of + {ok,UpdateReq} -> + {ok,UpdateReq,SequenceNumber}; + {fault,Cause,UpdateReq} -> + {fault,Cause,UpdateReq,SequenceNumber}; + {'EXIT',Reason} -> + io:format("hej",[]), + {fault,193,EmptyUpdateReq,SequenceNumber,Reason} + end; +decode_gtpc_msg(<<0:3, + _:4, + 0:1, + 20:8, + _Length:16, + SequenceNumber:16, + _FlowLabel:16, + _SNDCP_N_PDU_Number:8, + _:3/binary-unit:8, + TID:8/binary-unit:8, + _InformationElements/binary>>) -> + {ok,TID2} = tid_internal_storage(TID,[]), + DeleteReq = #sesT_deleteReqV0{tid = TID2}, + {ok,DeleteReq,SequenceNumber}; +decode_gtpc_msg(<<0:3, + _:4, + 0:1, + 21:8, + _Length:16, + SequenceNumber:16, + _FlowLabel:16, + _SNDCP_N_PDU_Number:8, + _:3/binary-unit:8, + TID:8/binary-unit:8, + InformationElements/binary>>) -> + Errors = #protocolErrors{}, + {ok,TID2} = tid_internal_storage(TID,[]), + EmptyDeleteRes = #sesT_deleteResV0{tid = TID2}, + case catch decode_ie_delete_res(InformationElements,0,Errors,EmptyDeleteRes) of + {ok,DeleteRes} -> + {ok,DeleteRes,SequenceNumber}; + {fault,Cause,DeleteRes} -> + {fault,Cause,DeleteRes,SequenceNumber}; + {'EXIT',_Reason} -> + {fault,193,EmptyDeleteRes,SequenceNumber} + end; +decode_gtpc_msg(_GTP_C_Message) -> + {fault}. + +decode_ie_create(<<>>,PresentIEs,Errors,CreateReq) -> + if + PresentIEs band 1917 /= 1917 -> + {fault,202,CreateReq}; + true -> + case Errors of + #protocolErrors{invalidManIE = true} -> + {fault,201,CreateReq}; + #protocolErrors{outOfSequence = true} -> + {fault,193,CreateReq}; + #protocolErrors{incorrectOptIE = true} -> + {fault,203,CreateReq}; + _ -> + {ok,CreateReq} + end + end; +decode_ie_create(<<6:8, + QoSElement:3/binary-unit:8, + Rest/binary>>,PresentIEs,Errors,CreateReq) -> + if + PresentIEs band 1 == 1 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 1 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + <<_:2, + DelayClass:3, + ReliabilityClass:3, + PeakThroughput:4, + _:1, + PrecedenceClass:3, + _:3, + MeanThroughput:5>> = QoSElement, + QoS = #sesT_qualityOfServiceV0{delayClass = DelayClass, + reliabilityClass = ReliabilityClass, + peakThroughput = PeakThroughput, + precedenceClass = PrecedenceClass, + meanThroughput = MeanThroughput}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{qos = QoS}, + decode_ie_create(Rest,PresentIEs bor 1,UpdatedErrors,UpdatedCreateReq); + true -> + <<_:2, + DelayClass:3, + ReliabilityClass:3, + PeakThroughput:4, + _:1, + PrecedenceClass:3, + _:3, + MeanThroughput:5>> = QoSElement, + QoS = #sesT_qualityOfServiceV0{delayClass = DelayClass, + reliabilityClass = ReliabilityClass, + peakThroughput = PeakThroughput, + precedenceClass = PrecedenceClass, + meanThroughput = MeanThroughput}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{qos = QoS}, + decode_ie_create(Rest,PresentIEs bor 1,Errors,UpdatedCreateReq) + end; +decode_ie_create(<<14:8, + Recovery:8, + Rest/binary>>,PresentIEs,Errors,CreateReq) -> + if + PresentIEs band 2 == 2 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 2 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{recovery = Recovery}, + decode_ie_create(Rest,PresentIEs bor 2,UpdatedErrors,UpdatedCreateReq); + true -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{recovery = Recovery}, + decode_ie_create(Rest,PresentIEs bor 2,Errors,UpdatedCreateReq) + end; +decode_ie_create(<<15:8, + _:6, + SelectionMode:2, + Rest/binary>>,PresentIEs,Errors,CreateReq) -> + if + PresentIEs band 4 == 4 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 4 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{selMode = selection_mode_internal_storage(SelectionMode)}, + decode_ie_create(Rest,PresentIEs bor 4,UpdatedErrors,UpdatedCreateReq); + true -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{selMode = selection_mode_internal_storage(SelectionMode)}, + decode_ie_create(Rest,PresentIEs bor 4,Errors,UpdatedCreateReq) + end; +decode_ie_create(<<16:8, + FlowLabel:16, + Rest/binary>>,PresentIEs,Errors,CreateReq) -> + if + PresentIEs band 8 == 8 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 8 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{flowLblData = FlowLabel}, + decode_ie_create(Rest,PresentIEs bor 8,UpdatedErrors,UpdatedCreateReq); + true -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{flowLblData = FlowLabel}, + decode_ie_create(Rest,PresentIEs bor 8,Errors,UpdatedCreateReq) + end; +decode_ie_create(<<17:8, + FlowLabel:16, + Rest/binary>>,PresentIEs,Errors,CreateReq) -> + if + PresentIEs band 16 == 16 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 16 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{flowLblSig = FlowLabel}, + decode_ie_create(Rest,PresentIEs bor 16,UpdatedErrors,UpdatedCreateReq); + true -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{flowLblSig = FlowLabel}, + decode_ie_create(Rest,PresentIEs bor 16,Errors,UpdatedCreateReq) + end; +decode_ie_create(<<128:8, + Length:16, + More/binary>>,PresentIEs,Errors,CreateReq) -> + <<PDPElement:Length/binary-unit:8, + Rest/binary>> = More, + if + PresentIEs band 32 == 32 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 32 -> + case pdp_addr_internal_storage(PDPElement) of + {ok,PDPAddress} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{endUserAdd = PDPAddress}, + decode_ie_create(Rest,PresentIEs bor 32,UpdatedErrors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true, + outOfSequence = true}, + decode_ie_create(Rest,PresentIEs bor 32,UpdatedErrors,CreateReq) + end; + true -> + case pdp_addr_internal_storage(PDPElement) of + {ok,PDPAddress} -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{endUserAdd = PDPAddress}, + decode_ie_create(Rest,PresentIEs bor 32,Errors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true}, + decode_ie_create(Rest,PresentIEs bor 32,UpdatedErrors,CreateReq) + end + end; +decode_ie_create(<<131:8, + Length:16, + More/binary>>,PresentIEs,Errors,CreateReq) -> + <<APNElement:Length/binary-unit:8, + Rest/binary>> = More, + if + PresentIEs band 64 == 64 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 64 -> + case catch apn_internal_storage(APNElement,[]) of + {ok,APN} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{accPointName = APN}, + decode_ie_create(Rest,PresentIEs bor 64,UpdatedErrors,UpdatedCreateReq); + _ -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true, + invalidManIE = true}, + decode_ie_create(Rest,PresentIEs bor 64,UpdatedErrors,CreateReq) + end; + true -> + case catch apn_internal_storage(APNElement,[]) of + {ok,APN} -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{accPointName = APN}, + decode_ie_create(Rest,PresentIEs bor 64,Errors,UpdatedCreateReq); + _ -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true}, + decode_ie_create(Rest,PresentIEs bor 64,UpdatedErrors,CreateReq) + end + end; +decode_ie_create(<<132:8, + Length:16, + More/binary>>,PresentIEs,Errors,CreateReq) -> + <<ConfigurationElement:Length/binary-unit:8, + Rest/binary>> = More, + if + PresentIEs band 128 == 128 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 128 -> + case catch pco_internal_storage(ConfigurationElement) of + {ok,PCO} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{protConOpt = PCO}, + decode_ie_create(Rest,PresentIEs bor 128,UpdatedErrors,UpdatedCreateReq); + _ -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true, + incorrectOptIE = true}, + decode_ie_create(Rest,PresentIEs bor 128,UpdatedErrors,CreateReq) + end; + true -> + case catch pco_internal_storage(ConfigurationElement) of + {ok,PCO} -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{protConOpt = PCO}, + decode_ie_create(Rest,PresentIEs bor 128,Errors,UpdatedCreateReq); + _ -> + UpdatedErrors = Errors#protocolErrors{incorrectOptIE = true}, + decode_ie_create(Rest,PresentIEs bor 128,UpdatedErrors,CreateReq) + end + end; +decode_ie_create(<<133:8, + Length:16, + More/binary>>,PresentIEs,Errors,CreateReq) -> + <<AddressElement:Length/binary-unit:8, + Rest/binary>> = More, + if + PresentIEs band 768 == 768 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 512 -> + if + PresentIEs band 256 == 0 -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{sgsnAddSig = GSNAddr}, + decode_ie_create(Rest,PresentIEs bor 256,UpdatedErrors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true, + outOfSequence = true}, + decode_ie_create(Rest,PresentIEs bor 256,UpdatedErrors,CreateReq) + end; + true -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{sgsnAddUser = GSNAddr}, + decode_ie_create(Rest,PresentIEs bor 512,UpdatedErrors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true, + outOfSequence = true}, + decode_ie_create(Rest,PresentIEs bor 512,UpdatedErrors,CreateReq) + end + end; + PresentIEs < 256 -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{sgsnAddSig = GSNAddr}, + decode_ie_create(Rest,PresentIEs bor 256,Errors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true}, + decode_ie_create(Rest,PresentIEs bor 256,UpdatedErrors,CreateReq) + end; + true -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{sgsnAddUser = GSNAddr}, + decode_ie_create(Rest,PresentIEs bor 512,Errors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true}, + decode_ie_create(Rest,PresentIEs bor 512,UpdatedErrors,CreateReq) + end + end; +decode_ie_create(<<134:8, + Length:16, + More/binary>>,PresentIEs,Errors,CreateReq) -> + <<MSISDNElement:Length/binary-unit:8, + Rest/binary>> = More, + if + PresentIEs band 1024 == 1024 -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + PresentIEs > 1024 -> + case msisdn_internal_storage(MSISDNElement,[]) of + {ok,MSISDN} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedCreateReq = CreateReq#sesT_createReqV0{msisdn = MSISDN}, + decode_ie_create(Rest,PresentIEs bor 1024,UpdatedErrors,UpdatedCreateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true, + invalidManIE = true}, + decode_ie_create(Rest,PresentIEs bor 1024,UpdatedErrors,CreateReq) + end; + true -> + UpdatedCreateReq = CreateReq#sesT_createReqV0{msisdn = #mvsT_msisdn{value = MSISDNElement}}, + decode_ie_create(Rest,PresentIEs bor 1024,Errors,UpdatedCreateReq) + end; +decode_ie_create(UnexpectedIE,PresentIEs,Errors,CreateReq) -> + case check_ie(UnexpectedIE) of + {defined_ie,Rest} -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + {handled_ie,Rest} -> + decode_ie_create(Rest,PresentIEs,Errors,CreateReq); + {unhandled_ie} -> + {fault,193,CreateReq} + end. + +decode_ie_update(<<>>,PresentIEs,Errors,UpdateReq) -> + if + PresentIEs band 61 /= 61 -> + {fault,202,UpdateReq}; + true -> + case Errors of + #protocolErrors{invalidManIE = true} -> + {fault,201,UpdateReq}; + #protocolErrors{outOfSequence = true} -> + {fault,193,UpdateReq}; + #protocolErrors{incorrectOptIE = true} -> + {fault,203,UpdateReq}; + _ -> + {ok,UpdateReq} + end + end; +decode_ie_update(<<6:8, + QoSElement:3/binary-unit:8, + Rest/binary>>,PresentIEs,Errors,UpdateReq) -> + if + PresentIEs band 1 == 1 -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + PresentIEs > 1 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + <<_:2, + DelayClass:3, + ReliabilityClass:3, + PeakThroughput:4, + _:1, + PrecedenceClass:3, + _:3, + MeanThroughput:5>> = QoSElement, + QoS = #sesT_qualityOfServiceV0{delayClass = DelayClass, + reliabilityClass = ReliabilityClass, + peakThroughput = PeakThroughput, + precedenceClass = PrecedenceClass, + meanThroughput = MeanThroughput}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{qos = QoS}, + decode_ie_update(Rest,PresentIEs bor 1,UpdatedErrors,UpdatedUpdateReq); + true -> + <<_:2, + DelayClass:3, + ReliabilityClass:3, + PeakThroughput:4, + _:1, + PrecedenceClass:3, + _:3, + MeanThroughput:5>> = QoSElement, + QoS = #sesT_qualityOfServiceV0{delayClass = DelayClass, + reliabilityClass = ReliabilityClass, + peakThroughput = PeakThroughput, + precedenceClass = PrecedenceClass, + meanThroughput = MeanThroughput}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{qos = QoS}, + decode_ie_update(Rest,PresentIEs bor 1,Errors,UpdatedUpdateReq) + end; +decode_ie_update(<<14:8, + Recovery:8, + Rest/binary>>,PresentIEs,Errors,UpdateReq) -> + if + PresentIEs band 2 == 2 -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + PresentIEs > 2 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{recovery = Recovery}, + decode_ie_update(Rest,PresentIEs bor 2,UpdatedErrors,UpdatedUpdateReq); + true -> + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{recovery = Recovery}, + decode_ie_update(Rest,PresentIEs bor 2,Errors,UpdatedUpdateReq) + end; +decode_ie_update(<<16:8, + FlowLabel:16, + Rest/binary>>,PresentIEs,Errors,UpdateReq) -> + if + PresentIEs band 4 == 4 -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + PresentIEs > 4 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{flowLblData = FlowLabel}, + decode_ie_update(Rest,PresentIEs bor 4,UpdatedErrors,UpdatedUpdateReq); + true -> + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{flowLblData = FlowLabel}, + decode_ie_update(Rest,PresentIEs bor 4,Errors,UpdatedUpdateReq) + end; +decode_ie_update(<<17:8, + FlowLabel:16, + Rest/binary>>,PresentIEs,Errors,UpdateReq) -> + if + PresentIEs band 8 == 8 -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + PresentIEs > 8 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{flowLblSig = FlowLabel}, + decode_ie_update(Rest,PresentIEs bor 8,UpdatedErrors,UpdatedUpdateReq); + true -> + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{flowLblSig = FlowLabel}, + decode_ie_update(Rest,PresentIEs bor 8,Errors,UpdatedUpdateReq) + end; +decode_ie_update(<<133:8, + Length:16, + More/binary>>,PresentIEs,Errors,UpdateReq) -> + <<AddressElement:Length/binary-unit:8, + Rest/binary>> = More, + if + PresentIEs band 48 == 48 -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + PresentIEs > 32 -> + if + PresentIEs band 16 == 0 -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{sgsnAddSig = GSNAddr}, + decode_ie_update(Rest,PresentIEs bor 16,UpdatedErrors,UpdatedUpdateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true, + outOfSequence = true}, + decode_ie_update(Rest,PresentIEs bor 16,UpdatedErrors,UpdateReq) + end; + true -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{sgsnAddUser = GSNAddr}, + decode_ie_update(Rest,PresentIEs bor 32,UpdatedErrors,UpdatedUpdateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true, + outOfSequence = true}, + decode_ie_update(Rest,PresentIEs bor 32,UpdatedErrors,UpdateReq) + end + end; + PresentIEs < 16 -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{sgsnAddSig = GSNAddr}, + decode_ie_update(Rest,PresentIEs bor 16,Errors,UpdatedUpdateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true}, + decode_ie_update(Rest,PresentIEs bor 16,UpdatedErrors,UpdateReq) + end; + true -> + case gsn_addr_internal_storage(AddressElement) of + {ok,GSNAddr} -> + UpdatedUpdateReq = UpdateReq#sesT_updateReqV0{sgsnAddUser = GSNAddr}, + decode_ie_update(Rest,PresentIEs bor 32,Errors,UpdatedUpdateReq); + {fault} -> + UpdatedErrors = Errors#protocolErrors{invalidManIE = true}, + decode_ie_update(Rest,PresentIEs bor 32,UpdatedErrors,UpdateReq) + end + end; +decode_ie_update(UnexpectedIE,PresentIEs,Errors,UpdateReq) -> + case check_ie(UnexpectedIE) of + {defined_ie,Rest} -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + {handled_ie,Rest} -> + decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); + {unhandled_ie} -> + {fault,193,UpdateReq} + end. + +decode_ie_delete_res(<<>>,PresentIEs,Errors,DeleteRes) -> + if + PresentIEs band 1 /= 1 -> + {fault,202,DeleteRes}; + true -> + case Errors of + #protocolErrors{invalidManIE = true} -> + {fault,201,DeleteRes}; + #protocolErrors{outOfSequence = true} -> + {fault,193,DeleteRes}; + #protocolErrors{incorrectOptIE = true} -> + {fault,203,DeleteRes}; + _ -> + {ok,DeleteRes} + end + end; +decode_ie_delete_res(<<1:8, + Cause:8, + Rest/binary>>,PresentIEs,Errors,DeleteRes) -> + if + PresentIEs band 1 == 1 -> + decode_ie_delete_res(Rest,PresentIEs,Errors,DeleteRes); + PresentIEs > 1 -> + UpdatedErrors = Errors#protocolErrors{outOfSequence = true}, + UpdatedDeleteRes = DeleteRes#sesT_deleteResV0{cause = Cause}, + decode_ie_delete_res(Rest,PresentIEs bor 1,UpdatedErrors,UpdatedDeleteRes); + true -> + UpdatedDeleteRes = DeleteRes#sesT_deleteResV0{cause = Cause}, + decode_ie_delete_res(Rest,PresentIEs bor 1,Errors,UpdatedDeleteRes) + end; +decode_ie_delete_res(UnexpectedIE,PresentIEs,Errors,DeleteRes) -> + case check_ie(UnexpectedIE) of + {defined_ie,Rest} -> + decode_ie_delete_res(Rest,PresentIEs,Errors,DeleteRes); + {handled_ie,Rest} -> + decode_ie_delete_res(Rest,PresentIEs,Errors,DeleteRes); + {unhandled_ie} -> + {fault,193,DeleteRes} + end. + +check_ie(<<1:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<2:8, + _:8/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<3:8, + _:6/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<4:8, + _:4/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<5:8, + _:4/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<6:8, + _:3/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<8:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<9:8, + _:28/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<11:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<12:8, + _:3/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<13:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<14:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<15:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<16:8, + _:16, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<17:8, + _:16, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<18:8, + _:32, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<19:8, + _:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<127:8, + _:4/binary-unit:8, + Rest/binary>>) -> + {defined_ie,Rest}; +check_ie(<<1:1, + _:7, + Length:16, + More/binary>>) -> + if + Length > size(More) -> + {unhandled_ie}; + true -> + <<_:Length/binary-unit:8, + Rest/binary>> = More, + {handled_ie,Rest} + end; +check_ie(_UnhandledIE) -> + {unhandled_ie}. + +tid_internal_storage(Bin,_) -> + Size = size(Bin) - 1, + <<Front:Size/binary, + NSAPI:4, + DigitN:4>> = Bin, + Result = case DigitN of + 15 -> + #mvsgT_tid{imsi = #mvsgT_imsi{value = Front}, + nsapi = NSAPI}; + _ -> + #mvsgT_tid{imsi = #mvsgT_imsi{value = <<Front/binary, + 15:4, + DigitN:4>>}, + nsapi = NSAPI} + end, + {ok,Result}. + +selection_mode_internal_storage(0) -> + subscribed; +selection_mode_internal_storage(1) -> + msRequested; +selection_mode_internal_storage(2) -> + sgsnSelected; +selection_mode_internal_storage(3) -> + sgsnSelected. + +pdp_addr_internal_storage(<<_:4, + 0:4, + 1:8>>) -> + {ok,#mvsgT_pdpAddressType{pdpTypeNbr = etsi_ppp, + address = []}}; +pdp_addr_internal_storage(<<_:4, + 0:4, + 2:8>>) -> + {ok,#mvsgT_pdpAddressType{pdpTypeNbr = etsi_osp_ihoss, + address = []}}; +pdp_addr_internal_storage(<<_:4, + 1:4, + 33:8>>) -> + {ok,#mvsgT_pdpAddressType{pdpTypeNbr = ietf_ipv4, + address = []}}; +pdp_addr_internal_storage(<<_:4, + 1:4, + 33:8, + IP_A:8, + IP_B:8, + IP_C:8, + IP_D:8>>) -> + {ok,#mvsgT_pdpAddressType{pdpTypeNbr = ietf_ipv4, + address = [IP_A,IP_B,IP_C,IP_D]}}; +pdp_addr_internal_storage(<<_:4, + 1:4, + 87:8, + IP_A:16, + IP_B:16, + IP_C:16, + IP_D:16, + IP_E:16, + IP_F:16, + IP_G:16, + IP_H:16>>) -> + {ok,#mvsgT_pdpAddressType{pdpTypeNbr = ietf_ipv6, + address = [IP_A,IP_B,IP_C,IP_D,IP_E,IP_F,IP_G,IP_H]}}; +pdp_addr_internal_storage(_PDP_ADDR) -> + {fault}. + +apn_internal_storage(<<>>,APN) -> + {ok,lists:reverse(APN)}; +apn_internal_storage(<<Length:8, + Rest/binary>>,APN) -> + <<Label:Length/binary-unit:8, + MoreAPNLabels/binary>> = Rest, + apn_internal_storage(MoreAPNLabels,[Label|APN]). + +pco_internal_storage(<<1:1, + _:4, + 0:3, + PPPConfigurationOptions/binary>>) -> + case ppp_configuration_options(PPPConfigurationOptions,#masT_pap{exists = false},[],[]) of + {ok,PAP,CHAP,IPCP} -> + {ok,#masT_protocolConfigOptions{pap = PAP, + chap = CHAP, + ipcp = IPCP}}; + {fault} -> + {fault} + end; +pco_internal_storage(<<1:1, + _:4, + 1:3, + _OSP_IHOSSConfigurationOptions/binary>>) -> + {ok,osp_ihoss}; +pco_internal_storage(_UnknownConfigurationOptions) -> + {fault}. + +ppp_configuration_options(<<>>,PAP,CHAP,IPCP) -> + {ok,PAP,CHAP,IPCP}; +ppp_configuration_options(<<49185:16, + Length:8, + More/binary>>,PAP,CHAP,IPCP) -> + <<_LCP:Length/binary-unit:8, + Rest/binary>> = More, + ppp_configuration_options(Rest,PAP,CHAP,IPCP); +ppp_configuration_options(<<49187:16, + _Length:8, + 1:8, + Identifier:8, + DataLength:16, + More/binary>>,_PAP,CHAP,IPCP) -> + ActualDataLength = DataLength - 4, + <<Data:ActualDataLength/binary-unit:8, + Rest/binary>> = More, + <<PeerIDLength:8, + PeerData/binary>> = Data, + <<PeerID:PeerIDLength/binary-unit:8, + PasswdLength:8, + PasswordData/binary>> = PeerData, + <<Password:PasswdLength/binary, + _Padding/binary>> = PasswordData, + ppp_configuration_options(Rest,#masT_pap{exists = true, + code = 1, + id = Identifier, + username = binary_to_list(PeerID), + password = binary_to_list(Password)},CHAP,IPCP); +ppp_configuration_options(<<49187:16, + Length:8, + More/binary>>,PAP,CHAP,IPCP) -> + <<PAP:Length/binary-unit:8, + Rest/binary>> = More, + ppp_configuration_options(Rest,PAP,CHAP,IPCP); +ppp_configuration_options(<<49699:16, + _Length:8, + 1:8, + Identifier:8, + DataLength:16, + More/binary>>,PAP,CHAP,IPCP) -> + ActualDataLength = DataLength - 4, + <<Data:ActualDataLength/binary-unit:8, + Rest/binary>> = More, + <<ValueSize:8, + ValueAndName/binary>> = Data, + <<Value:ValueSize/binary-unit:8, + Name/binary>> = ValueAndName, + ppp_configuration_options(Rest,PAP,[#masT_chap{code = 1, + id = Identifier, + value = binary_to_list(Value), + name = binary_to_list(Name)}|CHAP],IPCP); +ppp_configuration_options(<<49699:16, + _Length:8, + 2:8, + Identifier:8, + DataLength:16, + More/binary>>,PAP,CHAP,IPCP) -> + ActualDataLength = DataLength - 4, + <<Data:ActualDataLength/binary-unit:8, + Rest/binary>> = More, + <<ValueSize:8, + ValueAndName/binary>> = Data, + <<Value:ValueSize/binary-unit:8, + Name/binary>> = ValueAndName, + ppp_configuration_options(Rest,PAP,[#masT_chap{code = 2, + id = Identifier, + value = binary_to_list(Value), + name = binary_to_list(Name)}|CHAP],IPCP); +ppp_configuration_options(<<49699:16, + Length:8, + More/binary>>,PAP,CHAP,IPCP) -> + <<CHAP:Length/binary-unit:8, + Rest/binary>> = More, + ppp_configuration_options(Rest,PAP,CHAP,IPCP); +ppp_configuration_options(<<32801:16, + _Length:8, + 1:8, + Identifier:8, + OptionsLength:16, + More/binary>>,PAP,CHAP,IPCP) -> + ActualOptionsLength = OptionsLength - 4, + <<Options:ActualOptionsLength/binary-unit:8, + Rest/binary>> = More, + case Options of + <<3:8, + 6:8, + A1:8, + A2:8, + A3:8, + A4:8>> -> + ppp_configuration_options(Rest,PAP,CHAP,[#masT_ipcp{exists = true, + code = 1, + id = Identifier, + ipcpList = [#masT_ipcpData{type = 3, + ipAddress = #mvsgT_ipAddress{version = ipv4, + a1 = A1, + a2 = A2, + a3 = A3, + a4 = A4, + a5 = 0, + a6 = 0, + a7 = 0, + a8 = 0}, + rawMessage = binary_to_list(Options)}]}|IPCP]); + <<129:8, + 6:8, + B1:8, + B2:8, + B3:8, + B4:8>> -> + ppp_configuration_options(Rest,PAP,CHAP,[#masT_ipcp{exists = true, + code = 1, + id = Identifier, + ipcpList = [#masT_ipcpData{type = 129, + ipAddress = #mvsgT_ipAddress{version = ipv4, + a1 = B1, + a2 = B2, + a3 = B3, + a4 = B4}, + rawMessage = binary_to_list(Options)}]}|IPCP]); + <<131:8, + 6:8, + C1:8, + C2:8, + C3:8, + C4:8>> -> + ppp_configuration_options(Rest,PAP,CHAP,[#masT_ipcp{exists = true, + code = 1, + id = Identifier, + ipcpList = [#masT_ipcpData{type = 131, + ipAddress = #mvsgT_ipAddress{version = ipv4, + a1 = C1, + a2 = C2, + a3 = C3, + a4 = C4}, + rawMessage = binary_to_list(Options)}]}|IPCP]); + _ -> + ppp_configuration_options(Rest,PAP,CHAP,IPCP) + end; +ppp_configuration_options(<<_UnknownProtocolID:16, + Length:8, + More/binary>>,PAP,CHAP,IPCP) -> + <<_Skipped:Length/binary-unit:8, + Rest/binary>> = More, + ppp_configuration_options(Rest,PAP,CHAP,IPCP); +ppp_configuration_options(_Unhandled,_PAP,_CHAP,_IPCP) -> + {fault}. + +gsn_addr_internal_storage(<<IP_A:8, + IP_B:8, + IP_C:8, + IP_D:8>>) -> + {ok,#mvsgT_ipAddress{version = ipv4, + a1 = IP_A, + a2 = IP_B, + a3 = IP_C, + a4 = IP_D, + a5 = 0, + a6 = 0, + a7 = 0, + a8 = 0}}; +gsn_addr_internal_storage(<<IP_A:16, + IP_B:16, + IP_C:16, + IP_D:16, + IP_E:16, + IP_F:16, + IP_G:16, + IP_H:16>>) -> + {ok,#mvsgT_ipAddress{version = ipv6, + a1 = IP_A, + a2 = IP_B, + a3 = IP_C, + a4 = IP_D, + a5 = IP_E, + a6 = IP_F, + a7 = IP_G, + a8 = IP_H}}; +gsn_addr_internal_storage(_GSN_ADDR) -> + {fault}. + +msisdn_internal_storage(<<>>,MSISDN) -> + {ok,#mvsT_msisdn{value = lists:reverse(MSISDN)}}; +msisdn_internal_storage(<<255:8, + _Rest/binary>>,MSISDN) -> + {ok,#mvsT_msisdn{value = lists:reverse(MSISDN)}}; +msisdn_internal_storage(<<15:4, + DigitN:4, + _Rest/binary>>,MSISDN) when DigitN < 10 -> + {ok,#mvsT_msisdn{value = lists:reverse([DigitN bor 240|MSISDN])}}; +msisdn_internal_storage(<<DigitNplus1:4, + DigitN:4, + Rest/binary>>,MSISDN) when DigitNplus1 < 10, DigitN < 10 -> + NewMSISDN = [DigitNplus1 bsl 4 bor DigitN|MSISDN], + msisdn_internal_storage(Rest,NewMSISDN); +msisdn_internal_storage(_Rest,_MSISDN) -> + {fault}. |