1%% -*- erlang-indent-level: 2 -*- 2 3-module(bs_decode). 4 5-export([test/0]). 6 7-include("bs_decode_extract.hrl"). 8 9-define(PDU, <<30,16,0,90,0,1,0,0,255,255,255,255,81,67,101,7,0,0,0,96, 10 6,12,146,18,14,0,15,252,16,0,0,17,0,0,128,0,2,241,33,131, 11 0,20,7,97,112,110,48,49,51,97,8,101,114,105,99,115,115, 12 111,110,2,115,101,132,0,20,128,192,35,16,1,5,0,16,5,117, 13 115,101,114,53,5,112,97,115,115,53,133,0,4,172,28,12,1, 14 133,0,4,172,28,12,3,134,0,8,145,148,113,129,0,0,0,0>>). 15 16-define(RES, {ok,{sesT_createReqV0, 17 {mvsgT_tid,{mvsgT_imsi,<<81,67,101,7,0,0,0,240>>},6}, 18 [81,67,101,7,0,0,0,96], 19 {sesT_qualityOfServiceV0,1,4,9,2,18}, 20 0,subscribed,0,0, 21 {mvsgT_pdpAddressType,ietf_ipv4,[]}, 22 [<<"apn013a">>,<<"ericsson">>,<<"se">>], 23 {masT_protocolConfigOptions,[], 24 {masT_pap,true,1,5,"user5","pass5"}, 25 []}, 26 {mvsgT_ipAddress,ipv4,172,28,12,1,0,0,0,0}, 27 {mvsgT_ipAddress,ipv4,172,28,12,3,0,0,0,0}, 28 {mvsT_msisdn,<<145,148,113,129,0,0,0,0>>}}, 29 1}). 30 31test() -> 32 ?RES = decode_v0_opt(42, ?PDU), 33 ok. 34 35decode_v0_opt(0, Pdu) -> 36 decode_gtpc_msg(Pdu); 37decode_v0_opt(N, Pdu) -> 38 decode_gtpc_msg(Pdu), 39 decode_v0_opt(N-1, Pdu). 40 41%%% -------------------------------------------------------------- 42%%% #3.1.2 DECODE GTP-C MESSAGE 43%%% -------------------------------------------------------------- 44 45%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 46%%% Function : decode_gtpc_msg(GTP_C_Message)-> 47%%% {ok,Request,ControlDataUs} | 48%%% {fault,Cause,Request,ControlDataUs} 49%%% 50%%% Types : GTP_C_Message = binary(), GTP-C message from SGSN 51%%% Request = record(), Containing decoded request 52%%% ControlDataUS = record(), Containing header info 53%%% Cause = integer(), Error code 54%%% 55%%% Description: This function decodes a binary GTP-C message and 56%%% stores it in a record. Different records are used 57%%% for different message types. 58%%% 59%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 60 61%%% Create PDP Context Request 62%%% GTP97, SNN=0 63%%% (No SNDCP N-PDU number) 64decode_gtpc_msg(<<0:3,_:4,0:1,16:8,_Length:16,SequenceNumber:16, 65 _FlowLabel:16,_SNDCP_N_PDU_Number:8,_:3/binary-unit:8, 66 TID:8/binary-unit:8,InformationElements/binary>>) -> 67 Errors = #protocolErrors{}, 68 {ok,TID2} = tid_internal_storage(TID,[]), 69 EmptyCreateReq = #sesT_createReqV0{tid = TID2, 70 tidRaw = binary_to_list(TID)}, 71 case catch decode_ie_create(InformationElements,0,Errors,EmptyCreateReq) of 72 {ok,CreateReq} -> 73 {ok,CreateReq,SequenceNumber}; 74 {fault,Cause,CreateReq} -> 75 {fault,Cause,CreateReq,SequenceNumber}; 76 {'EXIT',_Reason} -> 77 {fault,193,EmptyCreateReq,SequenceNumber} 78 end; 79 80%%% Update PDP Context Request 81%%% GTP97, SNN=0 82%%% (No SNDCP N-PDU number) 83decode_gtpc_msg(<<0:3,_:4,0:1,18:8,_Length:16,SequenceNumber:16, 84 _FlowLabel:16,_SNDCP_N_PDU_Number:8,_:3/binary-unit:8, 85 TID:8/binary-unit:8,InformationElements/binary>>) -> 86 io:format("hej", []), 87 Errors = #protocolErrors{}, 88 {ok,TID2}=tid_internal_storage(TID,[]), 89 EmptyUpdateReq=#sesT_updateReqV0{tid=TID2, 90 tidRaw=binary_to_list(TID)}, 91 case catch decode_ie_update(InformationElements,0,Errors, 92 EmptyUpdateReq) of 93 {ok,UpdateReq} -> 94 {ok,UpdateReq,SequenceNumber}; 95 {fault,Cause,UpdateReq} -> 96 {fault,Cause,UpdateReq,SequenceNumber}; 97 {'EXIT',Reason} -> 98 io:format("hej", []), 99 {fault,193,EmptyUpdateReq,SequenceNumber, Reason} 100 end; 101 102%%% Delete PDP Context Request 103%%% GTP97, SNN=0 104%%% (No SNDCP N-PDU number) 105decode_gtpc_msg(<<0:3,_:4,0:1,20:8,_Length:16,SequenceNumber:16, 106 _FlowLabel:16,_SNDCP_N_PDU_Number:8,_:3/binary-unit:8, 107 TID:8/binary-unit:8,_InformationElements/binary>>) -> 108 {ok,TID2} = tid_internal_storage(TID,[]), 109 DeleteReq = #sesT_deleteReqV0{tid=TID2}, 110 {ok,DeleteReq,SequenceNumber}; 111 112%%% Delete PDP Context Response 113%%% GTP97, SNN=0 114%%% (No SNDCP N-PDU number) 115decode_gtpc_msg(<<0:3,_:4,0:1,21:8,_Length:16,SequenceNumber:16, 116 _FlowLabel:16,_SNDCP_N_PDU_Number:8,_:3/binary-unit:8, 117 TID:8/binary-unit:8,InformationElements/binary>>) -> 118 {ok,TID2} = tid_internal_storage(TID,[]), 119 EmptyDeleteRes = #sesT_deleteResV0{tid=TID2}, 120 case catch decode_ie_delete_res(InformationElements,0,EmptyDeleteRes) of 121 {ok, DeleteRes} -> 122 {ok,DeleteRes,SequenceNumber}; 123 {fault,Cause,DeleteRes} -> 124 {fault,Cause,DeleteRes,SequenceNumber}; 125 {'EXIT',_Reason} -> 126 {fault,193,EmptyDeleteRes,SequenceNumber} 127 end; 128 129%%% Error handling 130decode_gtpc_msg(_GTP_C_Message) -> 131 {fault}. 132 133%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 134%%% decode_ie_create/4 135%%% Decode information elements for Create PDP Context Request 136 137%%% All elements decoded 138decode_ie_create(<<>>,PresentIEs,Errors,CreateReq) -> 139 %% Check mandatory IE's 140 if 141 (PresentIEs band 16#77D) =/= 16#77D -> 142 {fault,202,CreateReq}; %Mandatory IE missing 143 true -> %OK 144 %% Check errors during decoding 145 case Errors of 146 #protocolErrors{invalidManIE=true} -> %Invalid mandatory IE 147 {fault,201,CreateReq}; %Mandatory IE incorrect 148 #protocolErrors{outOfSequence=true} -> %Out of sequence 149 {fault,193,CreateReq}; %Invalid message format 150 #protocolErrors{incorrectOptIE=true} -> %Incorrect optional IE 151 {fault,203,CreateReq}; %Optional IE incorrect 152 _ -> %OK 153 {ok,CreateReq} 154 end 155 end; 156 157%%% Quality of Service Profile, Mandatory 158decode_ie_create(<<6:8,QoSElement:3/binary-unit:8,Rest/binary>>,PresentIEs, 159 Errors,CreateReq) -> 160 if 161 (PresentIEs band 16#00000001) =:= 16#00000001 -> %Repeated IE's, ignore 162 decode_ie_create(Rest,PresentIEs,Errors,CreateReq); 163 PresentIEs > 16#00000001 -> %Out of sequence 164 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 165 <<_:2,DelayClass:3,ReliabilityClass:3, 166 PeakThroughput:4,_:1,PrecedenceClass:3, 167 _:3,MeanThroughput:5>> = QoSElement, 168 QoS=#sesT_qualityOfServiceV0{delayClass=DelayClass, 169 reliabilityClass=ReliabilityClass, 170 peakThroughput=PeakThroughput, 171 precedenceClass=PrecedenceClass, 172 meanThroughput=MeanThroughput}, 173 UpdatedCreateReq=CreateReq#sesT_createReqV0{qos=QoS}, 174 decode_ie_create(Rest,(PresentIEs bor 16#00000001), 175 UpdatedErrors,UpdatedCreateReq); 176 true -> %OK 177 <<_:2,DelayClass:3,ReliabilityClass:3, 178 PeakThroughput:4,_:1,PrecedenceClass:3, 179 _:3,MeanThroughput:5>> = QoSElement, 180 QoS=#sesT_qualityOfServiceV0{delayClass=DelayClass, 181 reliabilityClass=ReliabilityClass, 182 peakThroughput=PeakThroughput, 183 precedenceClass=PrecedenceClass, 184 meanThroughput=MeanThroughput}, 185 UpdatedCreateReq=CreateReq#sesT_createReqV0{qos=QoS}, 186 decode_ie_create(Rest,(PresentIEs bor 16#00000001), 187 Errors,UpdatedCreateReq) 188 end; 189 190%%% Recovery, Optional 191decode_ie_create(<<14:8,Recovery:8,Rest/binary>>, 192 PresentIEs,Errors,CreateReq) -> 193 if 194 (PresentIEs band 16#00000002) =:= 16#00000002 -> %Repeated IE, ignored 195 decode_ie_create(Rest,PresentIEs,Errors,CreateReq); 196 PresentIEs > 16#00000002 -> %Out of sequence 197 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 198 UpdatedCreateReq=CreateReq#sesT_createReqV0{recovery=Recovery}, 199 decode_ie_create(Rest,(PresentIEs bor 16#00000002), 200 UpdatedErrors,UpdatedCreateReq); 201 true -> %OK 202 UpdatedCreateReq=CreateReq#sesT_createReqV0{recovery=Recovery}, 203 decode_ie_create(Rest,(PresentIEs bor 16#00000002),Errors, 204 UpdatedCreateReq) 205 end; 206 207%%% Selection mode, Mandatory 208decode_ie_create(<<15:8,_:6,SelectionMode:2,Rest/binary>>,PresentIEs, 209 Errors,CreateReq) -> 210 if 211 (PresentIEs band 16#00000004) =:= 16#00000004 -> %Repeated IE, ignored 212 decode_ie_create(Rest,PresentIEs,Errors,CreateReq); 213 PresentIEs > 16#00000004 -> %Out of sequence 214 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 215 UpdatedCreateReq=CreateReq#sesT_createReqV0{ 216 selMode=selection_mode_internal_storage(SelectionMode)}, 217 decode_ie_create(Rest,(PresentIEs bor 16#00000004), 218 UpdatedErrors,UpdatedCreateReq); 219 true -> %OK 220 UpdatedCreateReq=CreateReq#sesT_createReqV0{ 221 selMode=selection_mode_internal_storage(SelectionMode)}, 222 decode_ie_create(Rest,(PresentIEs bor 16#00000004),Errors, 223 UpdatedCreateReq) 224 end; 225 226%%% Flow Label Data I, Mandatory 227decode_ie_create(<<16:8,FlowLabel:16,Rest/binary>>,PresentIEs,Errors,CreateReq) -> 228 if 229 (PresentIEs band 16#00000008) =:= 16#00000008 -> %Repeated IE, ignored 230 decode_ie_create(Rest,PresentIEs,Errors,CreateReq); 231 PresentIEs > 16#00000008 -> %Out of sequence 232 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 233 UpdatedCreateReq=CreateReq#sesT_createReqV0{flowLblData=FlowLabel}, 234 decode_ie_create(Rest,(PresentIEs bor 16#00000008), 235 UpdatedErrors,UpdatedCreateReq); 236 true -> %OK 237 UpdatedCreateReq=CreateReq#sesT_createReqV0{flowLblData=FlowLabel}, 238 decode_ie_create(Rest,(PresentIEs bor 16#00000008),Errors, 239 UpdatedCreateReq) 240 end; 241 242%%% Flow Label Signalling, Mandatory 243decode_ie_create(<<17:8,FlowLabel:16,Rest/binary>>,PresentIEs,Errors,CreateReq) -> 244 if 245 (PresentIEs band 16#00000010) =:= 16#00000010 -> %Repeated IE, ignored 246 decode_ie_create(Rest,PresentIEs,Errors,CreateReq); 247 PresentIEs > 16#00000010 -> %Out of sequence 248 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 249 UpdatedCreateReq=CreateReq#sesT_createReqV0{flowLblSig=FlowLabel}, 250 decode_ie_create(Rest,(PresentIEs bor 16#00000010), 251 UpdatedErrors,UpdatedCreateReq); 252 true -> %OK 253 UpdatedCreateReq=CreateReq#sesT_createReqV0{flowLblSig=FlowLabel}, 254 decode_ie_create(Rest,(PresentIEs bor 16#00000010),Errors, 255 UpdatedCreateReq) 256 end; 257 258%%% End User Address, Mandatory 259decode_ie_create(<<128:8,Length:16,More/binary>>,PresentIEs, 260 Errors,CreateReq) -> 261 <<PDPElement:Length/binary-unit:8,Rest/binary>> = More, 262 if 263 (PresentIEs band 16#00000020) =:= 16#00000020 -> %Repeated IE, ignore 264 decode_ie_create(Rest,PresentIEs,Errors,CreateReq); 265 PresentIEs > 16#00000020 -> %Out of sequence 266 case pdp_addr_internal_storage(PDPElement) of 267 {ok,PDPAddress} -> 268 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 269 UpdatedCreateReq=CreateReq#sesT_createReqV0{endUserAdd=PDPAddress}, 270 decode_ie_create(Rest,(PresentIEs bor 16#00000020), 271 UpdatedErrors,UpdatedCreateReq); 272 {fault} -> 273 UpdatedErrors=Errors#protocolErrors{invalidManIE=true, 274 outOfSequence=true}, 275 decode_ie_create(Rest,(PresentIEs bor 16#00000020), 276 UpdatedErrors,CreateReq) 277 end; 278 true -> %OK 279 case pdp_addr_internal_storage(PDPElement) of 280 {ok,PDPAddress} -> 281 UpdatedCreateReq=CreateReq#sesT_createReqV0{endUserAdd=PDPAddress}, 282 decode_ie_create(Rest,(PresentIEs bor 16#00000020), 283 Errors,UpdatedCreateReq); 284 {fault} -> 285 UpdatedErrors=Errors#protocolErrors{invalidManIE=true}, 286 decode_ie_create(Rest,(PresentIEs bor 16#00000020), 287 UpdatedErrors,CreateReq) 288 end 289 end; 290 291%%% Access Point Name, Mandatory 292decode_ie_create(<<131:8,Length:16,More/binary>>,PresentIEs, 293 Errors,CreateReq) -> 294 <<APNElement:Length/binary-unit:8,Rest/binary>> = More, 295 if 296 (PresentIEs band 16#00000040) =:= 16#00000040 -> %Repeated IE, ignore 297 decode_ie_create(Rest,PresentIEs,Errors,CreateReq); 298 PresentIEs > 16#00000040 -> %Out of sequence 299 case catch apn_internal_storage(APNElement,[]) of 300 {ok,APN} -> 301 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 302 UpdatedCreateReq=CreateReq#sesT_createReqV0{accPointName=APN}, 303 decode_ie_create(Rest,(PresentIEs bor 16#00000040), 304 UpdatedErrors,UpdatedCreateReq); 305 _ -> 306 UpdatedErrors=Errors#protocolErrors{outOfSequence=true, 307 invalidManIE=true}, 308 decode_ie_create(Rest,(PresentIEs bor 16#00000040), 309 UpdatedErrors,CreateReq) 310 end; 311 true -> %OK 312 case catch apn_internal_storage(APNElement,[]) of 313 {ok,APN} -> 314 UpdatedCreateReq=CreateReq#sesT_createReqV0{accPointName=APN}, 315 decode_ie_create(Rest,(PresentIEs bor 16#00000040), 316 Errors,UpdatedCreateReq); 317 _ -> 318 UpdatedErrors=Errors#protocolErrors{invalidManIE=true}, 319 decode_ie_create(Rest,(PresentIEs bor 16#00000040), 320 UpdatedErrors,CreateReq) 321 end 322 end; 323 324%%% Protocol Configuration Options, Optional 325decode_ie_create(<<132:8,Length:16,More/binary>>,PresentIEs,Errors,CreateReq) -> 326 <<ConfigurationElement:Length/binary-unit:8,Rest/binary>> = More, 327 if 328 (PresentIEs band 16#00000080) =:= 16#00000080 -> %Repeated IE, ignore 329 decode_ie_create(Rest,PresentIEs,Errors,CreateReq); 330 PresentIEs > 16#00000080 -> %Out of sequence 331 case catch pco_internal_storage(ConfigurationElement) of 332 {ok,PCO} -> 333 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 334 UpdatedCreateReq=CreateReq#sesT_createReqV0{protConOpt=PCO}, 335 decode_ie_create(Rest,(PresentIEs bor 16#00000080), 336 UpdatedErrors,UpdatedCreateReq); 337 _ -> 338 UpdatedErrors=Errors#protocolErrors{outOfSequence=true, 339 incorrectOptIE=true}, 340 decode_ie_create(Rest,(PresentIEs bor 16#00000080), 341 UpdatedErrors,CreateReq) 342 end; 343 true -> %OK 344 case catch pco_internal_storage(ConfigurationElement) of 345 {ok,PCO} -> 346 UpdatedCreateReq=CreateReq#sesT_createReqV0{protConOpt=PCO}, 347 decode_ie_create(Rest,(PresentIEs bor 16#00000080), 348 Errors,UpdatedCreateReq); 349 _ -> 350 UpdatedErrors=Errors#protocolErrors{incorrectOptIE=true}, 351 decode_ie_create(Rest,(PresentIEs bor 16#00000080), 352 UpdatedErrors,CreateReq) 353 end 354 end; 355 356%%% SGSN Address for signalling, Mandatory OR SGSN Address for user traffic, Mandatory 357decode_ie_create(<<133:8,Length:16,More/binary>>,PresentIEs, 358 Errors,CreateReq) -> 359 <<AddressElement:Length/binary-unit:8,Rest/binary>> = More, 360 if 361 (PresentIEs band 16#00000300) =:= 16#00000300 -> %Repeated IE, ignore 362 decode_ie_create(Rest,PresentIEs,Errors,CreateReq); 363 PresentIEs > 16#00000200 -> %Out of sequence 364 if 365 (PresentIEs band 16#00000100) =:= 16#00000000 -> %Signalling 366 case gsn_addr_internal_storage(AddressElement) of 367 {ok,GSNAddr} -> 368 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 369 UpdatedCreateReq=CreateReq#sesT_createReqV0{sgsnAddSig=GSNAddr}, 370 decode_ie_create(Rest,(PresentIEs bor 16#00000100), 371 UpdatedErrors,UpdatedCreateReq); 372 {fault} -> 373 UpdatedErrors=Errors#protocolErrors{invalidManIE=true, 374 outOfSequence=true}, 375 decode_ie_create(Rest,(PresentIEs bor 16#00000100), 376 UpdatedErrors,CreateReq) 377 end; 378 true -> % User traffic 379 case gsn_addr_internal_storage(AddressElement) of 380 {ok,GSNAddr} -> 381 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 382 UpdatedCreateReq=CreateReq#sesT_createReqV0{sgsnAddUser=GSNAddr}, 383 decode_ie_create(Rest,(PresentIEs bor 16#00000200), 384 UpdatedErrors,UpdatedCreateReq); 385 {fault} -> 386 UpdatedErrors=Errors#protocolErrors{invalidManIE=true, 387 outOfSequence=true}, 388 decode_ie_create(Rest,(PresentIEs bor 16#00000200), 389 UpdatedErrors,CreateReq) 390 end 391 end; 392 PresentIEs < 16#00000100 -> %OK, SGSN Address for signalling 393 case gsn_addr_internal_storage(AddressElement) of 394 {ok,GSNAddr} -> 395 UpdatedCreateReq=CreateReq#sesT_createReqV0{sgsnAddSig=GSNAddr}, 396 decode_ie_create(Rest,(PresentIEs bor 16#00000100), 397 Errors,UpdatedCreateReq); 398 {fault} -> 399 UpdatedErrors=Errors#protocolErrors{invalidManIE=true}, 400 decode_ie_create(Rest,(PresentIEs bor 16#00000100), 401 UpdatedErrors,CreateReq) 402 end; 403 true -> %OK, SGSN Address for user traffic 404 case gsn_addr_internal_storage(AddressElement) of 405 {ok,GSNAddr} -> 406 UpdatedCreateReq=CreateReq#sesT_createReqV0{sgsnAddUser=GSNAddr}, 407 decode_ie_create(Rest,(PresentIEs bor 16#00000200), 408 Errors,UpdatedCreateReq); 409 {fault} -> 410 UpdatedErrors=Errors#protocolErrors{invalidManIE=true}, 411 decode_ie_create(Rest,(PresentIEs bor 16#00000200), 412 UpdatedErrors,CreateReq) 413 end 414 end; 415 416%%% MSISDN, Mandatory 417decode_ie_create(<<134:8,Length:16,More/binary>>,PresentIEs, 418 Errors,CreateReq) -> 419 <<MSISDNElement:Length/binary-unit:8,Rest/binary>> = More, 420 if 421 (PresentIEs band 16#00000400) =:= 16#00000400 -> %Repeated IE, ignore 422 decode_ie_create(Rest,PresentIEs,Errors,CreateReq); 423 PresentIEs > 16#00000400 -> %Out of sequence 424 case msisdn_internal_storage(MSISDNElement,[]) of 425 {ok,MSISDN} -> 426 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 427 UpdatedCreateReq=CreateReq#sesT_createReqV0{msisdn=MSISDN}, 428 decode_ie_create(Rest,(PresentIEs bor 16#00000400), 429 UpdatedErrors,UpdatedCreateReq); 430 {fault} -> 431 UpdatedErrors=Errors#protocolErrors{outOfSequence=true,invalidManIE=true}, 432 decode_ie_create(Rest,(PresentIEs bor 16#00000400), 433 UpdatedErrors,CreateReq) 434 end; 435 true -> %OK 436 UpdatedCreateReq=CreateReq#sesT_createReqV0{msisdn=#mvsT_msisdn{value=MSISDNElement}}, 437 decode_ie_create(Rest,(PresentIEs bor 16#00000400), 438 Errors,UpdatedCreateReq) 439 440 end; 441 442%%% Private Extension, Optional 443%%% Not implemented 444 445%%% Error handling, Unexpected or unknown IE 446decode_ie_create(UnexpectedIE,PresentIEs,Errors,CreateReq) -> 447 case check_ie(UnexpectedIE) of 448 {defined_ie,Rest} -> %OK, ignored 449 decode_ie_create(Rest,PresentIEs,Errors,CreateReq); 450 {handled_ie,Rest} -> %OK, ignored 451 decode_ie_create(Rest,PresentIEs,Errors,CreateReq); 452 {unhandled_ie} -> %Error, abort decoding 453 {fault,193,CreateReq} %Invalid message format 454 end. 455 456%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 457%%% decode_ie_update/4 458%%% Decode information elements for Update PDP Context Request 459 460%%% All elements decoded 461decode_ie_update(<<>>,PresentIEs,Errors,UpdateReq) -> 462 %% Check mandatory IE's 463 if 464 (PresentIEs band 16#3D) =/= 16#3D -> 465 {fault,202,UpdateReq}; %Mandatory IE missing 466 true -> %OK 467 %% Check errors during decoding 468 case Errors of 469 #protocolErrors{invalidManIE=true} -> %Invalid mandatory IE 470 {fault,201,UpdateReq}; %Mandatory IE incorrect 471 #protocolErrors{outOfSequence=true} -> %Out of sequence 472 {fault,193,UpdateReq}; %Invalid message format 473 _ -> %OK 474 {ok,UpdateReq} 475 end 476 end; 477 478%%% Quality of Service Profile, Mandatory 479decode_ie_update(<<6:8,QoSElement:3/binary-unit:8,Rest/binary>>,PresentIEs, 480 Errors,UpdateReq) -> 481 if 482 (PresentIEs band 16#00000001) =:= 16#00000001 -> %Repeated IE's, ignore 483 decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); 484 PresentIEs > 16#00000001 -> %Out of sequence 485 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 486 <<_:2,DelayClass:3,ReliabilityClass:3, 487 PeakThroughput:4,_:1,PrecedenceClass:3, 488 _:3,MeanThroughput:5>> = QoSElement, 489 QoS=#sesT_qualityOfServiceV0{delayClass=DelayClass, 490 reliabilityClass=ReliabilityClass, 491 peakThroughput=PeakThroughput, 492 precedenceClass=PrecedenceClass, 493 meanThroughput=MeanThroughput}, 494 UpdatedUpdateReq=UpdateReq#sesT_updateReqV0{qos=QoS}, 495 decode_ie_update(Rest,(PresentIEs bor 16#00000001), 496 UpdatedErrors,UpdatedUpdateReq); 497 true -> %OK 498 <<_:2,DelayClass:3,ReliabilityClass:3, 499 PeakThroughput:4,_:1,PrecedenceClass:3, 500 _:3,MeanThroughput:5>> = QoSElement, 501 QoS=#sesT_qualityOfServiceV0{delayClass=DelayClass, 502 reliabilityClass=ReliabilityClass, 503 peakThroughput=PeakThroughput, 504 precedenceClass=PrecedenceClass, 505 meanThroughput=MeanThroughput}, 506 UpdatedUpdateReq=UpdateReq#sesT_updateReqV0{qos=QoS}, 507 decode_ie_update(Rest,(PresentIEs bor 16#00000001), 508 Errors,UpdatedUpdateReq) 509 end; 510 511%%% Recovery, Optional 512decode_ie_update(<<14:8,Recovery:8,Rest/binary>>,PresentIEs,Errors,UpdateReq) -> 513 if 514 (PresentIEs band 16#00000002) =:= 16#00000002 -> %Repeated IE, ignored 515 decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); 516 PresentIEs > 16#00000002 -> %Out of sequence 517 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 518 UpdatedUpdateReq=UpdateReq#sesT_updateReqV0{recovery=Recovery}, 519 decode_ie_update(Rest,(PresentIEs bor 16#00000002), 520 UpdatedErrors,UpdatedUpdateReq); 521 true -> %OK 522 UpdatedUpdateReq=UpdateReq#sesT_updateReqV0{recovery=Recovery}, 523 decode_ie_update(Rest,(PresentIEs bor 16#00000002),Errors, 524 UpdatedUpdateReq) 525 end; 526 527%%% Flow Label Data I, Mandatory 528decode_ie_update(<<16:8,FlowLabel:16,Rest/binary>>,PresentIEs,Errors,UpdateReq) -> 529 if 530 (PresentIEs band 16#00000004) =:= 16#00000004 -> %Repeated IE, ignored 531 decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); 532 PresentIEs > 16#00000004 -> %Out of sequence 533 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 534 UpdatedUpdateReq=UpdateReq#sesT_updateReqV0{flowLblData=FlowLabel}, 535 decode_ie_update(Rest,(PresentIEs bor 16#00000004), 536 UpdatedErrors,UpdatedUpdateReq); 537 true -> %OK 538 UpdatedUpdateReq=UpdateReq#sesT_updateReqV0{flowLblData=FlowLabel}, 539 decode_ie_update(Rest,(PresentIEs bor 16#00000004),Errors, 540 UpdatedUpdateReq) 541 end; 542 543%%% Flow Label Signalling, Mandatory 544decode_ie_update(<<17:8,FlowLabel:16,Rest/binary>>,PresentIEs,Errors,UpdateReq) -> 545 if 546 (PresentIEs band 16#00000008) =:= 16#00000008 -> %Repeated IE, ignored 547 decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); 548 PresentIEs > 16#00000008 -> %Out of sequence 549 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 550 UpdatedUpdateReq=UpdateReq#sesT_updateReqV0{flowLblSig=FlowLabel}, 551 decode_ie_update(Rest,(PresentIEs bor 16#00000008), 552 UpdatedErrors,UpdatedUpdateReq); 553 true -> %OK 554 UpdatedUpdateReq=UpdateReq#sesT_updateReqV0{flowLblSig=FlowLabel}, 555 decode_ie_update(Rest,(PresentIEs bor 16#00000008),Errors, 556 UpdatedUpdateReq) 557 end; 558 559%%% SGSN Address for signalling, Mandatory OR SGSN Address for user traffic, Mandatory 560decode_ie_update(<<133:8,Length:16,More/binary>>,PresentIEs, 561 Errors,UpdateReq) -> 562 <<AddressElement:Length/binary-unit:8,Rest/binary>> = More, 563 if 564 (PresentIEs band 16#00000030) =:= 16#00000030 -> %Repeated IE, ignore 565 decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); 566 PresentIEs > 16#00000020 -> %Out of sequence 567 if 568 (PresentIEs band 16#00000010) =:= 16#00000000 -> %Signalling 569 case gsn_addr_internal_storage(AddressElement) of 570 {ok,GSNAddr} -> 571 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 572 UpdatedUpdateReq=UpdateReq#sesT_updateReqV0{sgsnAddSig=GSNAddr}, 573 decode_ie_update(Rest,(PresentIEs bor 16#00000010), 574 UpdatedErrors,UpdatedUpdateReq); 575 {fault} -> 576 UpdatedErrors=Errors#protocolErrors{invalidManIE=true, 577 outOfSequence=true}, 578 decode_ie_update(Rest,(PresentIEs bor 16#00000010), 579 UpdatedErrors,UpdateReq) 580 end; 581 true -> % User traffic 582 case gsn_addr_internal_storage(AddressElement) of 583 {ok,GSNAddr} -> 584 UpdatedErrors=Errors#protocolErrors{outOfSequence=true}, 585 UpdatedUpdateReq=UpdateReq#sesT_updateReqV0{sgsnAddUser=GSNAddr}, 586 decode_ie_update(Rest,(PresentIEs bor 16#00000020), 587 UpdatedErrors,UpdatedUpdateReq); 588 {fault} -> 589 UpdatedErrors=Errors#protocolErrors{invalidManIE=true, 590 outOfSequence=true}, 591 decode_ie_update(Rest,(PresentIEs bor 16#00000020), 592 UpdatedErrors,UpdateReq) 593 end 594 end; 595 PresentIEs < 16#00000010 -> %OK, SGSN Address for signalling 596 case gsn_addr_internal_storage(AddressElement) of 597 {ok,GSNAddr} -> 598 UpdatedUpdateReq=UpdateReq#sesT_updateReqV0{sgsnAddSig=GSNAddr}, 599 decode_ie_update(Rest,(PresentIEs bor 16#00000010), 600 Errors,UpdatedUpdateReq); 601 {fault} -> 602 UpdatedErrors=Errors#protocolErrors{invalidManIE=true}, 603 decode_ie_update(Rest,(PresentIEs bor 16#00000010), 604 UpdatedErrors,UpdateReq) 605 end; 606 true -> %OK, SGSN Address for user traffic 607 case gsn_addr_internal_storage(AddressElement) of 608 {ok,GSNAddr} -> 609 UpdatedUpdateReq=UpdateReq#sesT_updateReqV0{sgsnAddUser=GSNAddr}, 610 decode_ie_update(Rest,(PresentIEs bor 16#00000020), 611 Errors,UpdatedUpdateReq); 612 {fault} -> 613 UpdatedErrors=Errors#protocolErrors{invalidManIE=true}, 614 decode_ie_update(Rest,(PresentIEs bor 16#00000020), 615 UpdatedErrors,UpdateReq) 616 end 617 end; 618 619%%% Private Extension, Optional 620%%% Not implemented 621 622%%% Error handling, Unexpected or unknown IE 623decode_ie_update(UnexpectedIE,PresentIEs,Errors,UpdateReq) -> 624 case check_ie(UnexpectedIE) of 625 {defined_ie,Rest} -> %OK, ignored 626 decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); 627 {handled_ie,Rest} -> %OK, ignored 628 decode_ie_update(Rest,PresentIEs,Errors,UpdateReq); 629 {unhandled_ie} -> %Error, abort decoding 630 {fault,193,UpdateReq} %Invalid message format 631 end. 632 633 634%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 635%%% decode_ie_delete_req/4 636%%% Decode information elements for Delete PDP Context Request 637 638%%% Private Extension, Optional 639%%% Not implemented 640 641 642%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 643%%% decode_ie_delete_res/4 644%%% Decode information elements for Delete PDP Context Response 645 646%%% All elements decoded 647decode_ie_delete_res(<<>>,PresentIEs,DeleteRes) -> 648 %% Check mandatory IE's 649 if 650 (PresentIEs band 16#0001) =/= 16#0001 -> 651 {fault,202,DeleteRes}; %Mandatory IE missing 652 true -> %OK 653 {ok,DeleteRes} 654 end; 655 656%%% Cause, Mandatory 657decode_ie_delete_res(<<1:8,Cause:8,Rest/binary>>,PresentIEs,DeleteRes) -> 658 if 659 (PresentIEs band 16#00000001) =:= 16#00000001 -> %Repeated IE, ignored 660 decode_ie_delete_res(Rest,PresentIEs,DeleteRes); 661 true -> %OK 662 UpdatedDeleteRes=DeleteRes#sesT_deleteResV0{cause=Cause}, 663 decode_ie_delete_res(Rest,(PresentIEs bor 16#00000001), 664 UpdatedDeleteRes) 665 end; 666 667%%% Private Extension, Optional 668%%% Not implemented 669 670%%% Error handling, Unexpected or unknown IE 671decode_ie_delete_res(UnexpectedIE,PresentIEs,DeleteRes) -> 672 case check_ie(UnexpectedIE) of 673 {defined_ie,Rest} -> %OK, ignored 674 decode_ie_delete_res(Rest,PresentIEs,DeleteRes); 675 {handled_ie,Rest} -> %OK, ignored 676 decode_ie_delete_res(Rest,PresentIEs,DeleteRes); 677 {unhandled_ie} -> %Error, abort decoding 678 {fault,193,DeleteRes} %Invalid message format 679 end. 680 681%%% -------------------------------------------------------------- 682%%% #3.2 COMMON INTERNAL FUNCTIONS 683%%% -------------------------------------------------------------- 684 685%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 686%%% check_ie/1 687%%% Check Information Element, Unexpected or Unknown 688check_ie(<<1:8,_:8,Rest/binary>>) -> 689 {defined_ie,Rest}; 690%%% IMSI 691check_ie(<<2:8,_:8/binary-unit:8,Rest/binary>>) -> 692 {defined_ie,Rest}; 693%%% RAI 694check_ie(<<3:8,_:6/binary-unit:8,Rest/binary>>) -> 695 {defined_ie,Rest}; 696%%% TTLI 697check_ie(<<4:8,_:4/binary-unit:8,Rest/binary>>) -> 698 {defined_ie,Rest}; 699%%% P-TMSI 700check_ie(<<5:8,_:4/binary-unit:8,Rest/binary>>) -> 701 {defined_ie,Rest}; 702%%% Quality of Service Profile 703check_ie(<<6:8,_:3/binary-unit:8,Rest/binary>>) -> 704 {defined_ie,Rest}; 705%%% Reordering Required 706check_ie(<<8:8,_:8,Rest/binary>>) -> 707 {defined_ie,Rest}; 708%%% Authentication Triplet 709check_ie(<<9:8,_:28/binary-unit:8,Rest/binary>>) -> 710 {defined_ie,Rest}; 711%%% MAP Cause 712check_ie(<<11:8,_:8,Rest/binary>>) -> 713 {defined_ie,Rest}; 714%%% P-TMSI Signature 715check_ie(<<12:8,_:3/binary-unit:8,Rest/binary>>) -> 716 {defined_ie,Rest}; 717%%% MS Validated 718check_ie(<<13:8,_:8,Rest/binary>>) -> 719 {defined_ie,Rest}; 720%%% Recovery 721check_ie(<<14:8,_:8,Rest/binary>>) -> 722 {defined_ie,Rest}; 723%%% Selection Mode 724check_ie(<<15:8,_:8,Rest/binary>>) -> 725 {defined_ie,Rest}; 726%%% Flow Label Data I 727check_ie(<<16:8,_:16,Rest/binary>>) -> 728 {defined_ie,Rest}; 729%%% Flow Label Signalling 730check_ie(<<17:8,_:16,Rest/binary>>) -> 731 {defined_ie,Rest}; 732%%% Flow Label Data II 733check_ie(<<18:8,_:32,Rest/binary>>) -> 734 {defined_ie,Rest}; 735%%% MS Not Reachable Reason 736check_ie(<<19:8,_:8,Rest/binary>>) -> 737 {defined_ie,Rest}; 738%%% Charging ID 739check_ie(<<127:8,_:4/binary-unit:8,Rest/binary>>) -> 740 {defined_ie,Rest}; 741%%% TLV element, skipped using Length 742check_ie(<<1:1,_:7,Length:16,More/binary>>) -> 743 if 744 Length > byte_size(More) -> 745 {unhandled_ie}; 746 true -> 747 <<_:Length/binary-unit:8,Rest/binary>> = More, 748 {handled_ie,Rest} 749 end; 750%%% TV element, unknown size. Can not be handled. 751check_ie(_UnhandledIE) -> 752 {unhandled_ie}. 753 754%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 755%%% tid_internal_storage/3 756%%% Convert TID binary to internal datatype 757tid_internal_storage(Bin,_) -> 758 Size = byte_size(Bin) - 1, 759 <<Front:Size/binary,NSAPI:4,DigitN:4>> = Bin, 760 Result = 761 case DigitN of 762 2#1111 -> 763 #mvsgT_tid{imsi = #mvsgT_imsi{value = Front}, nsapi = NSAPI}; 764 _ -> 765 Value = <<Front/binary,2#1111:4,DigitN:4>>, 766 #mvsgT_tid{imsi = #mvsgT_imsi{value = Value}, nsapi = NSAPI} 767 end, 768 {ok,Result}. 769%% tid_internal_storage(<<NSAPI:4,2#1111:4>>,IMSI) -> 770%% {ok,#mvsgT_tid{imsi=#mvsgT_imsi{value=lists:reverse(IMSI)}, 771%% nsapi=NSAPI}}; 772%% tid_internal_storage(<<NSAPI:4,DigitN:4>>,IMSI) when 773%% DigitN < 10 -> 774%% {ok,#mvsgT_tid{imsi=#mvsgT_imsi{value=lists:reverse([(DigitN bor 2#11110000)|IMSI])}, 775%% nsapi=NSAPI}}; 776%% tid_internal_storage(<<2#11111111:8,Rest/binary>>,IMSI) -> 777%% tid_internal_storage(Rest,IMSI); 778%% tid_internal_storage(<<2#1111:4,DigitN:4,Rest/binary>>,IMSI) when 779%% DigitN < 10 -> 780%% tid_internal_storage(Rest,[(DigitN bor 2#11110000)|IMSI]); 781%% tid_internal_storage(<<DigitNplus1:4,DigitN:4,Rest/binary>>,IMSI) when 782%% DigitNplus1 < 10, 783%% DigitN < 10 -> 784%% tid_internal_storage(Rest,[((DigitNplus1 bsl 4) bor DigitN)|IMSI]); 785%% tid_internal_storage(_Rest,_IMSI) -> 786%% {fault}. %% Mandatory IE incorrect 787 788%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 789%%% selection_mode_internal_storage/1 790%%% Convert Selection Mode integer to internal datatype (enum) 791selection_mode_internal_storage(0) -> 792 subscribed; 793selection_mode_internal_storage(1) -> 794 msRequested; 795selection_mode_internal_storage(2) -> 796 sgsnSelected; 797selection_mode_internal_storage(3) -> 798 sgsnSelected. 799 800%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 801%%% pdp_addr_internal_storage/1 802%%% Convert PDP address to internal datatype (record containing 803%%% addresstype and value) 804pdp_addr_internal_storage(<<_:4,0:4,1:8>>) -> 805 {ok,#mvsgT_pdpAddressType{pdpTypeNbr=etsi_ppp,address=[]}}; 806pdp_addr_internal_storage(<<_:4,0:4,2:8>>) -> 807 {ok,#mvsgT_pdpAddressType{pdpTypeNbr=etsi_osp_ihoss,address=[]}}; 808pdp_addr_internal_storage(<<_:4,1:4,16#21:8>>) -> 809 {ok,#mvsgT_pdpAddressType{pdpTypeNbr=ietf_ipv4,address=[]}}; 810pdp_addr_internal_storage(<<_:4,1:4,16#21:8,IP_A:8,IP_B:8,IP_C:8,IP_D:8>>) -> 811 {ok,#mvsgT_pdpAddressType{pdpTypeNbr=ietf_ipv4, 812 address=[IP_A,IP_B,IP_C,IP_D]}}; 813pdp_addr_internal_storage(<<_:4,1:4,16#57:8,IP_A:16,IP_B:16,IP_C:16,IP_D:16, 814 IP_E:16,IP_F:16,IP_G:16,IP_H:16>>) -> 815 {ok,#mvsgT_pdpAddressType{pdpTypeNbr=ietf_ipv6, 816 address=[IP_A,IP_B,IP_C,IP_D,IP_E,IP_F,IP_G,IP_H]}}; 817pdp_addr_internal_storage(_PDP_ADDR) -> 818 {fault}. 819 820%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 821%%% apn_internal_storage/2 822%%% Convert APN to internal datatype (List containing APN labels) 823apn_internal_storage(<<>>,APN) -> 824 {ok,lists:reverse(APN)}; 825apn_internal_storage(<<Length:8,Rest/binary>>,APN) -> 826 <<Label:Length/binary-unit:8,MoreAPNLabels/binary>> = Rest, 827 apn_internal_storage(MoreAPNLabels,[Label|APN]). 828 829%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 830%%% pco_internal_storage/1 831%%% Convert Protocol Configuration Options to internal datatype. 832%%% Implemented configuration options: 833%%% For PPP: 834%%% LCP - Not implemented 835%%% PAP - Authenticate request 836%%% CHAP - Challenge 837%%% - Response 838%%% IPCP - IP-Address 839%%% For OSP:IHOSS 840%%% Nothing implemented 841pco_internal_storage(<<1:1,_:4,0:3,PPPConfigurationOptions/binary>>) -> 842 case ppp_configuration_options(PPPConfigurationOptions, 843 #masT_pap{exists=false},[],[]) of 844 {ok,PAP,CHAP,IPCP} -> 845 {ok,#masT_protocolConfigOptions{pap=PAP,chap=CHAP,ipcp=IPCP}}; 846 {fault} -> 847 {fault} 848 end; 849pco_internal_storage(<<1:1,_:4,1:3,_OSP_IHOSSConfigurationOptions/binary>>) -> 850 {ok,osp_ihoss}; 851pco_internal_storage(_UnknownConfigurationOptions) -> 852 {fault}. %% Optional IE incorrect 853 854ppp_configuration_options(<<>>,PAP,CHAP,IPCP) -> 855 {ok,PAP,CHAP,IPCP}; 856ppp_configuration_options(<<16#C021:16,Length:8,More/binary>>,PAP,CHAP,IPCP) -> 857 %% LCP - Not implemented 858 <<_LCP:Length/binary-unit:8,Rest/binary>> = More, 859 ppp_configuration_options(Rest,PAP,CHAP,IPCP); 860ppp_configuration_options(<<16#C023:16,_Length:8,1:8,Identifier:8,DataLength:16, 861 More/binary>>,_PAP,CHAP,IPCP) -> 862 %% PAP - Authenticate request 863 ActualDataLength=DataLength-4, %% DataLength includes Code, Identifier and itself 864 <<Data:ActualDataLength/binary-unit:8,Rest/binary>> = More, 865 <<PeerIDLength:8,PeerData/binary>> = Data, 866 <<PeerID:PeerIDLength/binary-unit:8,PasswdLength:8,PasswordData/binary>> = PeerData, 867 <<Password:PasswdLength/binary,_Padding/binary>> = PasswordData, 868 ppp_configuration_options(Rest,#masT_pap{exists=true,code=1,id=Identifier, 869 username=binary_to_list(PeerID), 870 password=binary_to_list(Password)},CHAP,IPCP); 871 872ppp_configuration_options(<<16#C023:16,Length:8,More/binary>>,PAP,CHAP,IPCP) -> 873 %% PAP - Other, not implemented 874 <<_PAP:Length/binary-unit:8,Rest/binary>> = More, 875 ppp_configuration_options(Rest,PAP,CHAP,IPCP); 876ppp_configuration_options(<<16#C223:16,_Length:8,1:8,Identifier:8,DataLength:16, 877 More/binary>>,PAP,CHAP,IPCP) -> 878 %% CHAP - Challenge 879 ActualDataLength=DataLength-4, %% DataLength includes Code, Identifier and itself 880 <<Data:ActualDataLength/binary-unit:8,Rest/binary>> = More, 881 <<ValueSize:8,ValueAndName/binary>> = Data, 882 <<Value:ValueSize/binary-unit:8,Name/binary>> = ValueAndName, 883 ppp_configuration_options(Rest,PAP,[#masT_chap{code=1,id=Identifier, 884 value=binary_to_list(Value), 885 name=binary_to_list(Name)}|CHAP], 886 IPCP); 887ppp_configuration_options(<<16#C223:16,_Length:8,2:8,Identifier:8,DataLength:16, 888 More/binary>>,PAP,CHAP,IPCP) -> 889 %% CHAP - Response 890 ActualDataLength=DataLength-4, %% DataLength includes Code, Identifier and itself 891 <<Data:ActualDataLength/binary-unit:8,Rest/binary>> = More, 892 <<ValueSize:8,ValueAndName/binary>> = Data, 893 <<Value:ValueSize/binary-unit:8,Name/binary>> = ValueAndName, 894 ppp_configuration_options(Rest,PAP,[#masT_chap{code=2,id=Identifier, 895 value=binary_to_list(Value), 896 name=binary_to_list(Name)}|CHAP], 897 IPCP); 898ppp_configuration_options(<<16#C223:16,Length:8,More/binary>>,PAP,CHAP,IPCP) -> 899 %% CHAP - Other, not implemented 900 <<_CHAP:Length/binary-unit:8,Rest/binary>> = More, 901 ppp_configuration_options(Rest,PAP,CHAP,IPCP); 902ppp_configuration_options(<<16#8021:16,_Length:8,1:8,Identifier:8,OptionsLength:16, 903 More/binary>>,PAP,CHAP,IPCP) -> 904 %% IPCP - Configure request 905 ActualOptionsLength=OptionsLength-4, %% OptionsLength includes Code, Identifier and itself 906 <<Options:ActualOptionsLength/binary-unit:8,Rest/binary>> = More, 907 case Options of 908 <<3:8,6:8,A1:8,A2:8,A3:8,A4:8>> -> 909 %% IP Address, version 4 910 ppp_configuration_options(Rest,PAP,CHAP, 911 [#masT_ipcp{exists=true,code=1, 912 id=Identifier, 913 ipcpList=[#masT_ipcpData{type=3,ipAddress= 914 #mvsgT_ipAddress{version=ipv4, 915 a1=A1,a2=A2, 916 a3=A3,a4=A4, 917 a5=0,a6=0, 918 a7=0,a8=0}, 919 rawMessage=binary_to_list(Options)}]}|IPCP]); 920 <<129:8,6:8,B1:8,B2:8,B3:8,B4:8>> -> 921 %% IP Address, version 4 922 ppp_configuration_options(Rest,PAP,CHAP, 923 [#masT_ipcp{exists=true,code=1, 924 id=Identifier, 925 ipcpList=[#masT_ipcpData{type=129,ipAddress= 926 #mvsgT_ipAddress{version=ipv4, 927 a1=B1,a2=B2, 928 a3=B3,a4=B4}, 929 rawMessage=binary_to_list(Options)}]}|IPCP]); 930 931 <<131:8,6:8,C1:8,C2:8,C3:8,C4:8>> -> 932 %% IP Address, version 4 933 ppp_configuration_options(Rest,PAP,CHAP, 934 [#masT_ipcp{exists=true,code=1, 935 id=Identifier, 936 ipcpList=[#masT_ipcpData{type=131,ipAddress= 937 #mvsgT_ipAddress{version=ipv4, 938 a1=C1,a2=C2, 939 a3=C3,a4=C4}, 940 rawMessage=binary_to_list(Options)}]}|IPCP]); 941 _ -> 942 ppp_configuration_options(Rest,PAP,CHAP,IPCP) 943 end; 944ppp_configuration_options(<<_UnknownProtocolID:16,Length:8,More/binary>>, 945 PAP,CHAP,IPCP) -> 946 <<_Skipped:Length/binary-unit:8,Rest/binary>> = More, 947 ppp_configuration_options(Rest,PAP,CHAP,IPCP); 948ppp_configuration_options(_Unhandled,_PAP,_CHAP,_IPCP) -> 949 {fault}. 950 951%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 952%%% gsn_addr_internal_storage/1 953%%% Convert GSN Address to internal datatype 954gsn_addr_internal_storage(<<IP_A:8,IP_B:8,IP_C:8,IP_D:8>>) -> 955 {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}}; 956gsn_addr_internal_storage(<<IP_A:16,IP_B:16,IP_C:16,IP_D:16, 957 IP_E:16,IP_F:16,IP_G:16,IP_H:16>>) -> 958 {ok,#mvsgT_ipAddress{version=ipv6,a1=IP_A,a2=IP_B,a3=IP_C,a4=IP_D, 959 a5=IP_E,a6=IP_F,a7=IP_G,a8=IP_H}}; 960gsn_addr_internal_storage(_GSN_ADDR) -> 961 {fault}. 962 963%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 964%%% msisdn_internal_storage/3 965%%% Convert MSISDN binary to internal datatype (TBCD-octet list) 966 967msisdn_internal_storage(<<>>,MSISDN) -> 968 {ok,#mvsT_msisdn{value=lists:reverse(MSISDN)}}; 969msisdn_internal_storage(<<2#11111111:8,_Rest/binary>>,MSISDN) -> 970 {ok,#mvsT_msisdn{value=lists:reverse(MSISDN)}}; 971msisdn_internal_storage(<<2#1111:4,DigitN:4,_Rest/binary>>,MSISDN) when 972 DigitN < 10 -> 973 {ok,#mvsT_msisdn{value=lists:reverse([(DigitN bor 2#11110000)|MSISDN])}}; 974msisdn_internal_storage(<<DigitNplus1:4,DigitN:4,Rest/binary>>,MSISDN) when 975 DigitNplus1 < 10, 976 DigitN < 10 -> 977 NewMSISDN=[((DigitNplus1 bsl 4) bor DigitN)|MSISDN], 978 msisdn_internal_storage(Rest,NewMSISDN); 979msisdn_internal_storage(_Rest,_MSISDN) -> 980 {fault}. %% Mandatory IE incorrect 981