From e7d5812d17e1165492ad342c016c80bad24ae9aa Mon Sep 17 00:00:00 2001 From: Daniel <0xc0decafe@users.noreply.github.com> Date: Wed, 5 Oct 2016 12:42:59 +0200 Subject: Structure changed in regard to erlang OTP. Added binary release. --- .gitignore | 3 +- README.md | 30 +- config.example | 16 +- prepare_n_build.sh | 5 + rebar.config | 1 + rel/reltool.config | 46 +++ releases/ss7MAPer-v0.2_linux_x64.tar.bz2 | Bin 0 -> 21840063 bytes src/map_msgs.erl | 99 +++--- src/map_tests.erl | 540 ++++++++++++++++++++++++++++++ src/ss7MAPer.app.src | 13 + src/ss7MAPer.erl | 153 +++++++++ src/ss7MAPer.hrl | 29 ++ src/ss7MAPer_app.erl | 12 + src/ss7MAPer_sup.erl | 34 ++ src/ss7_helper.erl | 53 +++ src/ss7test.app.src | 12 - src/ss7test_app.erl | 555 ------------------------------- src/ss7test_app.hrl | 6 - src/ss7test_helper.erl | 53 --- src/ss7test_sup.erl | 27 -- src/tcap.erl | 41 +++ ss7test.iml | 20 -- 22 files changed, 1003 insertions(+), 745 deletions(-) create mode 100644 rel/reltool.config create mode 100644 releases/ss7MAPer-v0.2_linux_x64.tar.bz2 create mode 100644 src/map_tests.erl create mode 100644 src/ss7MAPer.app.src create mode 100644 src/ss7MAPer.erl create mode 100644 src/ss7MAPer.hrl create mode 100644 src/ss7MAPer_app.erl create mode 100644 src/ss7MAPer_sup.erl create mode 100644 src/ss7_helper.erl delete mode 100644 src/ss7test.app.src delete mode 100644 src/ss7test_app.erl delete mode 100644 src/ss7test_app.hrl delete mode 100644 src/ss7test_helper.erl delete mode 100644 src/ss7test_sup.erl create mode 100644 src/tcap.erl delete mode 100644 ss7test.iml diff --git a/.gitignore b/.gitignore index 8e46d5a..3cac764 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ deps *.plt erl_crash.dump ebin -rel/example_project +rel/ss7MAPer +rel/files .concrete/DEV_MODE .rebar diff --git a/README.md b/README.md index 2bb452b..87c66e9 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,12 @@ SS7 MAP (pen-)testing toolkit +## Binary releases + +As a lot of people run into problems building the tool, there are binary releases which can be found here: https://github.com/ernw/ss7MAPer/tree/master/releases + +If you use the binary version, skip right over the next chapter. + ## Get it running You will need: @@ -100,21 +106,35 @@ Be sure to modify it to your needs. ## Running the tool +### Running a source build + To run the tool one needs to start a rebar shell: cd ss7MAPer rebar shell -Then the SIGTRAN connection needs to be established: +Start the application and its dependencies with: - Pid = ss7test_app:start(1, "./configfile"). + application:start(sasl). + application:start(ss7MAPer). If everything is set up correctly the m3ua connection comes up. -To run the HLR tests, simply enter: +### Running the binary release - Pid ! {test_hlr}. +Run the application by starting it from the root directory: + cd ss7MAPer + ./bin/ss7MAPer console +If everything is set up correctly the m3ua connection comes up. - +### Using the tool + +Once the application is started, there are some commands that can be executed from the erlang command line: + + - ss7MAPer:test\_hlr() + - ss7MAPer:test\_msc() + - ss7MAPer:test\_smsc() + +and each of them does exactly as its called, running MAP tests against the targets defined in the config file. diff --git a/config.example b/config.example index a12e3ba..a688bb3 100644 --- a/config.example +++ b/config.example @@ -1,14 +1,14 @@ {sctp, [ - {local_ip, {10,1,2,3}}, + {local_ip, {127,0,0,2}}, {local_port, 2905}, - {remote_ip, {10,1,2,4}}, + {remote_ip, {127,0,0,1}}, {remote_port, 2905} ]}. {m3ua, [ {local_pc, 10}, {remote_pc, 20}, {network_ind, 2}, - {route_ctx, 1}, + {route_ctx, 6}, {asp_id, none}, {net_appearance, none} ]}. @@ -18,10 +18,12 @@ {target, [ {gt_hlr, [1,2,3,4,5,6,7,8,9,0]}, {gt_vlr, [1,2,3,4,5,6,7,8,9,1]}, - {gt_msc, []}, - {gt_sgsn, []}, + {gt_msc, [1,2,3,4,5,6,7,8,9,2]}, + {gt_sgsn, [1,2,3,4,5,6,7,8,9,3]}, + {gt_gmsc, [1,2,3,4,5,6,7,8,9,4]}, + {gt_smsc, [1,2,3,4,5,6,7,8,9,5]}, {msisdn, [0,9,8,7,6,5,4,3,2,1]}, - {imsi, [0,9,8,7,6,5,4,3,2,1]}, - {service_center, [9,8,7,6,5,4,3,2,1]} + {imsi, "01020304050607f8"}, + {service_center, [9,8,7,6,5,4,3,2,1]}, {forward_number, [9,8,7,6,5,4,3,2,0]} ]}. diff --git a/prepare_n_build.sh b/prepare_n_build.sh index a3b2fbb..5f2abb2 100755 --- a/prepare_n_build.sh +++ b/prepare_n_build.sh @@ -43,3 +43,8 @@ cp deps/signerl/SCCP/itu/include/sccp.hrl deps/osmo_sccp/src/ cp deps/signerl/TCAP/include/tcap.hrl deps/osmo_map/src/ rebar co + +cd rel/ +rebar create-node nodeid=ss7MAPer +cd .. +rebar generate diff --git a/rebar.config b/rebar.config index 06fd2c9..7eaa7a4 100644 --- a/rebar.config +++ b/rebar.config @@ -5,3 +5,4 @@ {osmo_map, "1", {git, "git://git.osmocom.org/erlang/osmo_map/", "master"}} ]}. {eunit_opts, [verbose, {report,{eunit_surefire,[{dir,"."}]}}]}. +{sub_dirs, ["rel"]}. diff --git a/rel/reltool.config b/rel/reltool.config new file mode 100644 index 0000000..ab6c57b --- /dev/null +++ b/rel/reltool.config @@ -0,0 +1,46 @@ +%% -*- mode: erlang -*- +%% ex: ft=erlang +{sys, [ + {lib_dirs, ["../src", "../deps"]}, + {erts, [{mod_cond, derived}, {app_file, strip}]}, + {app_file, strip}, + {rel, "ss7MAPer", "1", + [ + kernel, + stdlib, + sasl, + ss7MAPer + ]}, + {rel, "start_clean", "", + [ + kernel, + stdlib + ]}, + {boot_rel, "ss7MAPer"}, + {profile, embedded}, + {incl_cond, derived}, + {excl_archive_filters, [".*"]}, %% Do not archive built libs + {excl_sys_filters, ["^bin/(?!start_clean.boot)", + "^erts.*/bin/(dialyzer|typer)", + "^erts.*/(doc|info|include|lib|man|src)"]}, + {excl_app_filters, ["\.gitignore"]}, + {app, hipe, [{incl_cond, exclude}]}, + {app, ss7MAPer, [{mod_cond, app}, {incl_cond, include}, {lib_dir, ".."}]} + ]}. + +{target_dir, "ss7MAPer"}. + +{overlay, [ + {mkdir, "log/sasl"}, + {copy, "files/erl", "\{\{erts_vsn\}\}/bin/erl"}, + {copy, "files/nodetool", "releases/\{\{rel_vsn\}\}/nodetool"}, + {copy, "ss7MAPer/bin/start_clean.boot", + "\{\{erts_vsn\}\}/bin/start_clean.boot"}, + {copy, "files/ss7MAPer", "bin/ss7MAPer"}, + {copy, "files/ss7MAPer.cmd", "bin/ss7MAPer.cmd"}, + {copy, "files/start_erl.cmd", "bin/start_erl.cmd"}, + %% Following line may be safely removed in new projects + {copy, "files/install_upgrade.escript", "bin/install_upgrade.escript"}, + {copy, "files/sys.config", "releases/\{\{rel_vsn\}\}/sys.config"}, + {copy, "files/vm.args", "releases/\{\{rel_vsn\}\}/vm.args"} + ]}. diff --git a/releases/ss7MAPer-v0.2_linux_x64.tar.bz2 b/releases/ss7MAPer-v0.2_linux_x64.tar.bz2 new file mode 100644 index 0000000..da8bb3e Binary files /dev/null and b/releases/ss7MAPer-v0.2_linux_x64.tar.bz2 differ diff --git a/src/map_msgs.erl b/src/map_msgs.erl index e70b9c7..56c320c 100644 --- a/src/map_msgs.erl +++ b/src/map_msgs.erl @@ -2,7 +2,7 @@ -author('Daniel Mende '). -include_lib("osmo_map/src/map.hrl"). --include("ss7test_app.hrl"). +-include("ss7MAPer.hrl"). -compile([export_all]). @@ -17,19 +17,19 @@ % MAP Definitions -define(IMSI, hex:hexstr_to_bin("01020304050607f8")). --define(IMSI_AS_NR, ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, +-define(IMSI_AS_NR, ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_LAND_MOBILE, [0,1,0,2,0,3,0,4,0,5,0,6,0,7,8])). -define(TMSI, hex:hexstr_to_bin("1234")). --define(MSISDN, ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, +-define(MSISDN, ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, [1,2,3,4,5,6,7,8,9,0])). -define(SERVICE_CENTER_ADDRESS, hex:hexstr_to_bin("010203040506f1")). -define(SERVICE_CENTER_ADDRESS_OA, hex:hexstr_to_bin("010203040506f1")). -define(SERVICE_CENTER_ADDRESS_DA, hex:hexstr_to_bin("010203040506f1")). --define(GGSN, ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, +-define(GGSN, ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, [1,2,3,4,5,6,7,8,9,0])). @@ -37,16 +37,16 @@ % SMS Definitions -define(ORIGINATING_ADDRESS, hex:hexstr_to_bin("0b9010203040506f1")). --define(DESTINATION_ADDRESS, ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, +-define(DESTINATION_ADDRESS, ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, [1,2,3,4,5,6,7,8,9,0])). --define(SOURCE_ADDRESS, ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, +-define(SOURCE_ADDRESS, ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, [1,2,3,4,5,6,7,8,9,0])). -define(SMS_DEST_NR, [1,2,3,4,5,6,7,8,9,0]). -define(SMS_SRC_NR, [1,2,3,4,5,6,7,8,9,0]). --define(IMEI, ss7test_helper:encode_phonenumner([1,2,3,4,5,6,7,8,9,0])). +-define(IMEI, ss7_helper:encode_phonenumner([1,2,3,4,5,6,7,8,9,0])). %%%%%%%%%%%%%%%%%%%%%%%%%%%% % helper @@ -93,7 +93,7 @@ create_testSMSPDU_mt() -> EncSMSText = 'sms_7bit_encoding':to_7bit(SMSText), SMSLen = string:len(SMSText), Timestamp = hex:hexstr_to_bin("51803001258080"), - DA = ss7test_helper:encode_phonenumber(?NUMBER_EXTENSION_NONE, + DA = ss7_helper:encode_phonenumber(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, ?SMS_SRC_NR), <<0:4, 4:4, DA/binary, 0:8, 0:8, Timestamp/binary, SMSLen:8, EncSMSText/binary>>. @@ -102,17 +102,17 @@ create_testSMSPDU_mo() -> SMSText = "ERNW test SMS 31337", EncSMSText = 'sms_7bit_encoding':to_7bit(SMSText), SMSLen = string:len(SMSText), - DA = ss7test_helper:encode_phonenumber(?NUMBER_EXTENSION_NONE, + DA = ss7_helper:encode_phonenumber(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, ?SMS_DEST_NR), <<1:8, 23:8, DA/binary, 0:8, 0:8, SMSLen:8, EncSMSText/binary>>. create_mt_forwardSM_v2() -> - create_mt_forwardSM_v2(create_testSMSPDU_mt()). -create_mt_forwardSM_v2(SMSPDU) -> + create_mt_forwardSM_v2(create_testSMSPDU_mt(), ?IMSI, ?SERVICE_CENTER_ADDRESS_DA). +create_mt_forwardSM_v2(SMSPDU, Imsi, Scada) -> MapData = { 'ForwardSM-Arg', - {imsi, ?IMSI}, - {serviceCentreAddressOA, ?SERVICE_CENTER_ADDRESS_DA}, + {imsi, Imsi}, + {serviceCentreAddressOA, Scada}, SMSPDU, asn1_NOVALUE, asn1_NOVALUE}, Dialog = build_dialog_request({0,4,0,0,1,0,25,2}), @@ -132,11 +132,11 @@ create_mt_forwardSM(SMSPDU) -> encode_map_pdu(Dialog, 44, MapData). create_mo_forwardSM_v2() -> - create_mo_forwardSM_v2(create_testSMSPDU_mo()). -create_mo_forwardSM_v2(SMSPDU) -> + create_mo_forwardSM_v2(create_testSMSPDU_mo(), ?SERVICE_CENTER_ADDRESS_DA, ?MSISDN). +create_mo_forwardSM_v2(SMSPDU, Scada, Msisdn) -> MapData = { 'ForwardSM-Arg', - {serviceCentreAddressDA, ?SERVICE_CENTER_ADDRESS_DA}, - {msisdn, ?MSISDN}, + {serviceCentreAddressDA, Scada}, + {msisdn, Msisdn}, SMSPDU, asn1_NOVALUE, asn1_NOVALUE}, Dialog = build_dialog_request({0,4,0,0,1,0,21,2}), @@ -198,7 +198,7 @@ create_sendRoutingInfo(Msisdn, OrGsmSCF) -> basicCall, asn1_NOVALUE, asn1_NOVALUE, - ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, OrGsmSCF), %gsmc-OrGsmSCF-Address <<7,0,1,68,40,9,150,31>>, %callReferenceNumber @@ -249,37 +249,13 @@ create_sendRoutingInfo(Msisdn, OrGsmSCF) -> {ok, EncMapPDU} = map:encode('MapSpecificPDUs', MapPDU), EncMapPDU. -%~ create_sendRoutingInfoForGprs() -> - %~ MapData = {'SendRoutingInforForGprsArg', - %~ ?IMSI, - %~ asn1_NOVALUE, - %~ ?GGSN}, - %~ MapPDU = {'begin', - %~ {'MapSpecificPDUs_begin', - %~ get_transactionId(), - %~ {'EXTERNAL', - %~ {0,0,17,773,1,1,1}, - %~ asn1_NOVALUE,asn1_NOVALUE, - %~ {'single-ASN1-type',<<96,15,128,2,7,128,161,9,6,7,4,0,0,1,0,33,4>>}}, - %~ [{basicROS, - %~ {invoke, - %~ {'MapSpecificPDUs_begin_components_SEQOF_basicROS_invoke', - %~ {present,1}, - %~ asn1_NOVALUE, - %~ {local,24}, - %~ MapData}}}]}}, - %~ {ok, EncMapPDU} = map:encode('MapSpecificPDUs', MapPDU), - %~ EncMapPDU. - -%~ create_registerSS() -> - %~ create_registerSS(?IMSI, ?DESTINATION_ADDRESS). create_registerSS(Imsi, Origin, DestinationNumber) -> MapDialoguePDU = {'map-open', {'MAP-OpenInfo', - ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_LAND_MOBILE, Imsi), %destinationReference - ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, Origin), %originationReference asn1_NOVALUE }}, @@ -325,10 +301,10 @@ create_registerSS(Imsi, Origin, DestinationNumber) -> create_eraseSS(Imsi, Origin) -> MapDialoguePDU = {'map-open', {'MAP-OpenInfo', - ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_LAND_MOBILE, Imsi), %destinationReference - ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, Origin), %originationReference asn1_NOVALUE }}, @@ -371,10 +347,10 @@ create_updateLocation() -> create_updateLocation(Imsi, MscNr, VlrNr) -> MapData = {'UpdateLocationArg', Imsi, - ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, MscNr), %msc-Number - ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, VlrNr), %vlr-Number asn1_NOVALUE, %<<59,151,2,0>>, %lmsi @@ -416,7 +392,7 @@ create_anyTimeInerrogation(Imsi, GsmSCF) -> 'NULL',asn1_NOVALUE,asn1_NOVALUE, asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE, asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}, - ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, GsmSCF), %gsmSCF-Address asn1_NOVALUE}, @@ -468,7 +444,7 @@ create_purgeMs() -> create_purgeMs(Imsi, VlrNr) -> MapData = {'PurgeMs-Arg', Imsi, - ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, VlrNr), %VLR number asn1_NOVALUE, %SGSN number @@ -481,8 +457,10 @@ create_purgeMs(Imsi, VlrNr) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%% create_provideSubscriberInfo() -> + create_provideSubscriberInfo(?IMSI). +create_provideSubscriberInfo(Imsi) -> MapData = {'ProvideSubscriberInfoArg', - ?IMSI, + Imsi, asn1_NOVALUE, {'RequestedInfoMAP-MS-DataTypes', 'NULL', %locationInformation @@ -515,20 +493,22 @@ create_sendIdentification() -> encode_map_pdu(Dialog, 55, MapData). create_provideRoamingNumber() -> + create_provideRoamingNumber(?IMSI, ?MSISDN, ?LOCAL_GLOBAL_TITLE, ?LOCAL_GLOBAL_TITLE). +create_provideRoamingNumber(Imsi, Msisdn, MscNr, GmscNr) -> MapData = {'ProvideRoamingNumberArg', - ?IMSI, - ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + Imsi, + ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, - [1,2,3,4,5,6,7,8,9]), %msc-Number - ?MSISDN, + MscNr), %msc-Number + Msisdn, asn1_NOVALUE, {'ExternalSignalInfo','gsm-0408', <<4,1,160>>, asn1_NOVALUE}, asn1_NOVALUE,asn1_NOVALUE, - ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, - [1,2,3,4,5,6,7,8,9,0]), %gmsc-Address + GmscNr), %gmsc-Address <<112,4,1,54,22,114,55>>, %callReferenceNumber asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE, asn1_NOVALUE, @@ -540,8 +520,10 @@ create_provideRoamingNumber() -> encode_map_pdu(Dialog, 4, MapData). create_cancelLocation() -> + create_cancelLocation(?IMSI). +create_cancelLocation(Imsi) -> MapData = {'CancelLocationArg', - {imsi,?IMSI}, + {imsi,Imsi}, updateProcedure, asn1_NOVALUE, asn1_NOVALUE}, @@ -587,4 +569,3 @@ create_insertSubscriberData() -> }, Dialog = build_dialog_request('subscriberDataMngtContext-v3'), encode_map_pdu(Dialog, 7, MapData). - diff --git a/src/map_tests.erl b/src/map_tests.erl new file mode 100644 index 0000000..b3fddb9 --- /dev/null +++ b/src/map_tests.erl @@ -0,0 +1,540 @@ +-module(map_tests). +-author('Daniel Mende '). + +-include_lib("osmo_ss7/include/sccp.hrl"). +-include("ss7MAPer.hrl"). + +-export([test_hlr/1, test_msc/1, test_smsc/1]). + +%~ ========= +%~ HLR TESTS +%~ ========= + +test_hlr(L) -> + LocalSsn = ?SCCP_SSN_MSC, + ok = sccp_user:bind_ssn(LocalSsn), + Gts = {L#loop_dat.gt_local, L#loop_dat.gt_hlr}, + test_sri(Gts, L), + test_srifs(Gts, L), + L2 = test_si(Gts, L), + test_sai(Gts, L2, 100), + test_sai(Gts, L2, 10), + test_sai(Gts, L2, 5), + test_rss(Gts, L2), + test_ess(Gts, L2), + test_ul(Gts, L2), + test_ati(Gts, L2), + test_pms(Gts, L2), + ok = sccp_user:unbind_ssn(LocalSsn, undefined), + L2. + +test_sri(Gts, L) -> + %~ ======== + %~ sendRoutingInfo + %~ ======== + io:format("~n\e[93;1m# Testing sendRoutingInfo...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_sendRoutingInfo(L#loop_dat.msisdn, L#loop_dat.gt_local)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for sendRoutingInfo~n~w~n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> + io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); + [{basicROS, + {returnResult, + {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', + {present,1},{'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', + {local,22},_}}}}|_] -> + io:format("\e[91;1mReceived SendRoutingInfoRes~n\e[39;49;0m"); + _ -> + io:format("\e[93;1mNo Error.~n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError decoding SendRoutingInfo\n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError no data received for SendRoutingInfo\n\e[39;49;0m") + after 2000 -> + io:format("\e[91;1mError timeout on receiving SendRoutingInfo\n\e[39;49;0m") + end, + L. + +test_srifs(Gts, L) -> + %~ ======== + %~ sendRoutingInfoForSM + %~ ======== + io:format("~n\e[93;1m# Testing sendRoutingInfoForSM...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_sendRoutingInfoForSM(L#loop_dat.msisdn, L#loop_dat.scenter)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for sendRoutingInfoForSM\n~w\n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}|_] -> + case {Present, Local} of + {1, 6} -> + io:format("\e[91;1mSubscriber is absent~n\e[39;49;0m"); + _ -> + io:format("\e[92;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]) + end; + [{basicROS, + {returnResult, + {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', + {present,1},{'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', + {local,45}, Res}}}}|_] -> + {'RoutingInfoForSM-Res',_, + {'LocationInfoWithLMSI',Loc,_,_,_,_},_,_} = Res, + io:format("\e[91;1mReceived routingInfoForSM, Mobile Station ~w", [ss7_helper:decode_phonenumber(Loc)]); + _ -> + io:format("\e[93;1mNo Error.~n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError decoding SendRoutingInfoForSM\n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError no data received for SendRoutingInfoForSM\n\e[39;49;0m") + after 2000 -> + io:format("\e[91;1mError timeout on receiving SendRoutingInfoForSM\n\e[39;49;0m") + end, + L. + +test_si(Gts, L) -> + %~ ======== + %~ sendImsi + %~ ======== + io:format("~n\e[93;1m# Testing sendImsi...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_sendImsi(L#loop_dat.msisdn)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for sendImsi\n~w\n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> + io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]), + L; + [{basicROS, + {returnResult, + {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', + {present,1}, + {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', + {local,58}, + Imsi }}}}|_] -> + io:format("\e[91;1mReceived IMSI ~w~n\e[39;49;0m", [ss7_helper:decode_imsi(Imsi)]), + L#loop_dat{imsi = Imsi} + end; + _-> + io:format("\e[91;1mError decoding sendImsi\n\e[39;49;0m"), + L + end; + _-> + io:format("\e[91;1mError no data received for sendImsi\n\e[39;49;0m"), + L + after 2000 -> + io:format("\e[91;1mError timeout on receiving sendImsi\n\e[39;49;0m"), + L + end. + +test_sai(Gts, L, Nr) -> + %~ ======== + %~ sendAuthenticationInfo + %~ ======== + io:format("~n\e[93;1m# Testing sendAuthenticationInfo...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_sendAuthenticationInfo(L#loop_dat.imsi, Nr)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for sendAuthenticationInfo\n~w\n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> + io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); + [{basicROS, {reject, _}}|_] -> + if + Nr>5 -> io:format("\e[92;1mAsked for ~w (>5) vectors, got rejected~n\e[39;49;0m", [Nr]); + Nr<6 -> io:format("\e[91;1mAsked for ~w (<=5) vectors, got rejected~n\e[39;49;0m", [Nr]) + end; + [{basicROS, + {returnResult, + {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', + {present,1}, {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', + {local,56}, {'SendAuthenticationInfoRes', + {quintupletList,ResList},_,_}}}}}|_] -> + NrRes = length(ResList), + if + Nr>5 -> + if + NrRes>5 -> io:format("\e[91;1mAsked for ~w vectors, got ~w (>5) result vectors~n\e[39;49;0m", [Nr,NrRes]) + end; + Nr<6 -> + if + NrRes==Nr -> io:format("\e[92;1mAsked for ~w vectors, got ~w (=~w) result vectors~n\e[39;49;0m", [Nr,NrRes,Nr]); + true -> io:format("\e[93;1mAsked for ~w vectors, got ~w (!=~w) result vectors~n\e[39;49;0m", [Nr,NrRes,Nr]) + end + end; + _ -> + io:format("\e[93;1mNo Error.~n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError decoding sendAuthenticationInfo\n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError no data received for sendAuthenticationInfo\n\e[39;49;0m") + after 2000 -> + io:format("\e[91;1mError timeout on receiving sendAuthenticationInfo\n\e[39;49;0m") + end, + L. + +test_rss(Gts, L) -> + %~ ======== + %~ registerSS + %~ ======== + io:format("~n\e[93;1m# Testing registerSS...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_registerSS(ss7_helper:decode_imsi(L#loop_dat.imsi), L#loop_dat.gt_vlr, L#loop_dat.fnumber)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for registerSS\n~w\n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> + io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); + [{basicROS, + {returnResult, + {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', + {present,1}, {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', + {local,10},_}}}}|_] -> + io:format("\e[91;1mReceived forwardingInfo, registerSS is working~n\e[39;49;0m"); + _ -> + io:format("\e[93;1mNo Error.~n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError decoding registerSS\n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError no data received for registerSS\n\e[39;49;0m") + after 2000 -> + io:format("\e[91;1mError timeout on receiving registerSS\n\e[39;49;0m") + end, + L. + +test_ess(Gts, L) -> + %~ ======== + %~ eraseSS + %~ ======== + io:format("~n\e[93;1m# Testing eraseSS...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_eraseSS(ss7_helper:decode_imsi(L#loop_dat.imsi), L#loop_dat.gt_vlr)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for eraseSS\n~w\n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> + io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); + [{basicROS, + {returnResult, + {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', + {present,1}, {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', + {local,11},_}}}}|_] -> + io:format("\e[91;1mReceived forwardingInfo, eraseSS is working~n\e[39;49;0m"); + _ -> + io:format("\e[93;1mNo Error.~n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError decoding eraseSS\n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError no data received for eraseSS\n\e[39;49;0m") + after 2000 -> + io:format("\e[91;1mError timeout on receiving eraseSS\n\e[39;49;0m") + end, + L. + +test_ul(Gts, L) -> + %~ ======== + %~ updateLocation + %~ ======== + io:format("~n\e[93;1m# Testing updateLocation...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_updateLocation(L#loop_dat.imsi, L#loop_dat.gt_local, L#loop_dat.gt_local)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for updateLocation\n~w\n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> + io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); + [{basicROS,{invoke,{'MapSpecificPDUs_continue_components_SEQOF_basicROS_invoke',{present,2},asn1_NOVALUE,{local,7},_}}}|_] -> + io:format("\e[91;1mReceived insertSubscriberData, updateLocation is working~n\e[39;49;0m"); + _ -> + io:format("\e[93;1mNo Error.~n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError decoding updateLocation\n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError no data received for updateLocation\n\e[39;49;0m") + after 2000 -> + io:format("\e[91;1mError timeout on receiving updateLocation\n\e[39;49;0m") + end, + L. + +test_ati(Gts, L) -> + %~ ======== + %~ anyTimeInterrogation + %~ ======== + io:format("~n\e[93;1m# Testing anyTimeInterrogation...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_anyTimeInerrogation(L#loop_dat.imsi, L#loop_dat.gt_local)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for anyTimeInerrogation\n~w\n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> + case {Present, Local} of + {1, 49} -> + io:format("\e[92;1manyTimeInterrogation is forbidden~n\e[39;49;0m"); + _ -> + io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]) + end; + _ -> + io:format("\e[93;1mNo Error.~n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError decoding anyTimeInerrogation\n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError no data received for anyTimeInerrogation\n\e[39;49;0m") + after 2000 -> + io:format("\e[91;1mError timeout on receiving anyTimeInerrogation\n\e[39;49;0m") + end, + L. + +test_pms(Gts, L) -> + %~ ======== + %~ purgeMS + %~ ======== + io:format("~n\e[93;1m# Testing purgeMS...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_purgeMs(L#loop_dat.imsi, L#loop_dat.gt_local)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for purgeMs\n~w\n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> + io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); + [{basicROS, + {returnResult, + {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', + {present,1},{'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', + {local,67},_}}}}|_] -> + io:format("\e[91;1mReceived purgeMS-Res, purgeMS is working~n\e[39;49;0m"); + _ -> + io:format("\e[93;1mNo Error.~n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError decoding purgeMs\n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError no data received for purgeMs\n\e[39;49;0m") + after 2000 -> + io:format("\e[91;1mError timeout on receiving purgeMs\n\e[39;49;0m") + end, + L. + +%~ ========= +%~ MSC TESTS +%~ ========= + +test_msc(L) -> + ok = sccp_user:bind_ssn(?SCCP_SSN_HLR), + Gts = {L#loop_dat.gt_local, L#loop_dat.gt_msc}, + test_psi(Gts, L), + test_prn(Gts, L), + test_cl(Gts, L), + ok = sccp_user:unbind_ssn(?SCCP_SSN_HLR, undefined), + ok = sccp_user:bind_ssn(?SCCP_SSN_MSC), + test_mt_fsm(Gts, L), + ok = sccp_user:unbind_ssn(?SCCP_SSN_MSC, undefined), + L. + +test_psi(Gts, L) -> + %~ ======== + %~ provideSubscriberInfo + %~ ======== + io:format("~n\e[93;1m# Testing provideSubscriberInfo...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_HLR, ?SCCP_SSN_VLR}, map_msgs:create_provideSubscriberInfo(L#loop_dat.imsi)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for provideSubscriberInfo~n~w~n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> + io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); + [{basicROS, + {returnResult, + {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', + {present,1},{'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', + {local,70},_}}}}|_] -> + io:format("\e[91;1mReceived provideSubscriberInfoRes~n\e[39;49;0m"); + _ -> + io:format("\e[93;1mNo Error.~n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError decoding provideSubscriberInfo\n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError no data received for provideSubscriberInfo\n\e[39;49;0m") + after 2000 -> + io:format("\e[91;1mError timeout on receiving provideSubscriberInfo\n\e[39;49;0m") + end, + L. + +test_prn(Gts, L) -> + %~ ======== + %~ provideRoamingNumber + %~ ======== + io:format("~n\e[93;1m# Testing provideRoamingNumber...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_HLR, ?SCCP_SSN_VLR}, map_msgs:create_provideRoamingNumber(L#loop_dat.imsi, L#loop_dat.msisdn, L#loop_dat.gt_msc, L#loop_dat.gt_gmsc)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for provideRoamingNumber~n~w~n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> + io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); + [{basicROS, + {returnResult, + {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', + {present,1},{'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', + {local,4},_}}}}|_] -> + io:format("\e[91;1mReceived provideRoamingNumberRes~n\e[39;49;0m"); + _ -> + io:format("\e[93;1mNo Error.~n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError decoding provideRoamingNumber\n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError no data received for provideRoamingNumber\n\e[39;49;0m") + after 2000 -> + io:format("\e[91;1mError timeout on receiving provideRoamingNumber\n\e[39;49;0m") + end, + L. + +test_cl(Gts, L) -> + %~ ======== + %~ cancelLocation + %~ ======== + io:format("~n\e[93;1m# Testing cancelLocation...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_HLR, ?SCCP_SSN_SGSN}, map_msgs:create_cancelLocation(L#loop_dat.imsi)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for cancelLocation~n~w~n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> + io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); + %~ [{basicROS, + %~ {returnResult, + %~ {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', + %~ {present,1},{'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', + %~ {local,70},_}}}}|_] -> + %~ io:format("\e[91;1mReceived cancelLocationRes~n\e[39;49;0m"); + _ -> + io:format("\e[93;1mNo Error.~n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError decoding cancelLocation\n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError no data received for cancelLocation\n\e[39;49;0m") + after 2000 -> + io:format("\e[91;1mError timeout on receiving cancelLocation\n\e[39;49;0m") + end, + L. + +test_mt_fsm(Gts, L) -> + %~ ======== + %~ mt_forwardSM + %~ ======== + io:format("~n\e[93;1m# Testing mt_forwardSM...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_MSC}, map_msgs:create_mt_forwardSM_v2(map_msgs:create_testSMSPDU_mt(), L#loop_dat.imsi, L#loop_dat.scenter)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for mt_forwardSM~n~w~n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> + io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); + [{basicROS, + {returnResult, + {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', + {present,1},asn1_NOVALUE}}}|_] -> + io:format("\e[91;1mReceived mt_forwardSM-Res~n\e[39;49;0m"); + _ -> + io:format("\e[93;1mNo Error.~n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError decoding mt_forwardSM\n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError no data received for mt_forwardSM\n\e[39;49;0m") + after 2000 -> + io:format("\e[91;1mError timeout on receiving mt_forwardSM\n\e[39;49;0m") + end, + L. + +%~ ========== +%~ SMSC TESTS +%~ ========== + +test_smsc(L) -> + ok = sccp_user:bind_ssn(?SCCP_SSN_MSC), + Gts = {L#loop_dat.gt_local, L#loop_dat.gt_smsc}, + test_mo_fsm(Gts, L), + ok = sccp_user:unbind_ssn(?SCCP_SSN_MSC, undefined), + L. + +test_mo_fsm(Gts, L) -> + %~ ======== + %~ mo_forwardSM + %~ ======== + io:format("~n\e[93;1m# Testing mo_forwardSM...\n\e[39;49;0m"), + tcap:send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_MSC}, map_msgs:create_mo_forwardSM_v2(map_msgs:create_testSMSPDU_mo(), L#loop_dat.scenter, L#loop_dat.msisdn)), + receive + {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> + case tcap:decode_tcap(Data) of + {ok, Results} -> + io:format("\e[97;1mGot answer for mo_forwardSM~n~w~n\e[39;49;0m", [Results]), + case Results of + [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> + io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); + [{basicROS, + {returnResult, + {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', + {present,1},asn1_NOVALUE}}}|_] -> + io:format("\e[91;1mReceived mo_forwardSM-Res~n\e[39;49;0m"); + _ -> + io:format("\e[93;1mNo Error.~n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError decoding mo_forwardSM\n\e[39;49;0m") + end; + _-> + io:format("\e[91;1mError no data received for mo_forwardSM\n\e[39;49;0m") + after 2000 -> + io:format("\e[91;1mError timeout on receiving mo_forwardSM\n\e[39;49;0m") + end, + L. + diff --git a/src/ss7MAPer.app.src b/src/ss7MAPer.app.src new file mode 100644 index 0000000..82ecc5b --- /dev/null +++ b/src/ss7MAPer.app.src @@ -0,0 +1,13 @@ +{application, ss7MAPer, + [ + {description, "SS7 MAP (Pen-)testing toolkit"}, + {vsn, "1"}, + {registered, [ss7test]}, + {applications, [ + kernel, + stdlib, + sasl + ]}, + {mod, { ss7MAPer_app, ["./config"]}}, + {env, []} + ]}. diff --git a/src/ss7MAPer.erl b/src/ss7MAPer.erl new file mode 100644 index 0000000..39268b7 --- /dev/null +++ b/src/ss7MAPer.erl @@ -0,0 +1,153 @@ +-module(ss7MAPer). +-author('Daniel Mende '). + +-behaviour(gen_server). + +-export([start_link/1]). +-export([init/1, handle_cast/2, handle_call/3, code_change/3, handle_info/2, terminate/2]). + +-export([test_hlr/0, test_msc/0, test_smsc/0]). + +-include_lib("osmo_ss7/include/osmo_util.hrl"). +-include_lib("osmo_ss7/include/osmo_ss7.hrl"). +-include_lib("osmo_ss7/include/m3ua.hrl"). +-include_lib("osmo_ss7/include/sccp.hrl"). +-include_lib("osmo_map/src/tcap_asn.hrl"). +-include("ss7MAPer.hrl"). + +%% change routing context in m3ua_code.erl => fixed +%% add pointcode to sccp in sccp_codec.erl +%% change network indicator in sccp_scrc.erl => fixed + + +start_link(Configfile) -> + gen_server:start_link({local, ?MODULE}, ?MODULE, [Configfile], []). + +init(Configfile) -> + {ok, connect(Configfile)}. + +connect(Configfile) -> + Config = case file:consult(Configfile) of + {ok, C} -> + C; + {error, E} -> + io:fwrite("\e[91;1mError reading config file ~p:~n~p~n\e[39;49;0m", [Configfile, E]), + exit(config_error) + end, + {sctp, SCTP_Config} = lists:keyfind(sctp, 1, Config), + {m3ua, M3UA_Config} = lists:keyfind(m3ua, 1, Config), + {sccp, Sccp} = lists:keyfind(sccp, 1, Config), + {target, Target} = lists:keyfind(target, 1, Config), + {gt_local, GT_Local} = lists:keyfind(gt_local, 1, Sccp), + {gt_hlr, GT_Hlr} = lists:keyfind(gt_hlr, 1, Target), + {gt_vlr, GT_Vlr} = lists:keyfind(gt_vlr, 1, Target), + {gt_msc, GT_Msc} = lists:keyfind(gt_msc, 1, Target), + {gt_sgsn, GT_Sgsn} = lists:keyfind(gt_sgsn, 1, Target), + {gt_gmsc, GT_Gmsc} = lists:keyfind(gt_gmsc, 1, Target), + {gt_smsc, GT_Smsc} = lists:keyfind(gt_smsc, 1, Target), + {msisdn, Msisdn} = lists:keyfind(msisdn, 1, Target), + {imsi, Imsi} = lists:keyfind(imsi, 1, Target), + Msisdn_enc = ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, + Msisdn), + {service_center, SCenter} = lists:keyfind(service_center, 1, Target), + SCenter_enc = ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, + SCenter), + {forward_number, FNumber} = lists:keyfind(forward_number, 1, Target), + FNumber_enc = ss7_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, + ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, + FNumber), + %~ error_logger:tty(false), + % start link server and create linkset + {ok, SS7linksPid} = ss7_links:start_link(), + sys:trace(ss7_links, ?TRACE), + {local_pc, Local_PC} = lists:keyfind(local_pc, 1, M3UA_Config), + {remote_pc, Remote_PC} = lists:keyfind(remote_pc, 1, M3UA_Config), + ok = ss7_links:register_linkset(Local_PC, Remote_PC, "test_linkset"), + %start route server and add route + {ok, SS7routesPid} = ss7_routes:start_link(), + %~ sys:trace(ss7_routes, ?TRACE), + ok = ss7_routes:create_route(Remote_PC, 16#ffff, "test_linkset"), + % create m3ua link + {local_ip, Local_IP} = lists:keyfind(local_ip, 1, SCTP_Config), + {local_port, Local_Port} = lists:keyfind(local_port, 1, SCTP_Config), + Local = #sigtran_peer{ip = Local_IP, port = Local_Port}, + {remote_ip, Remote_IP} = lists:keyfind(remote_ip, 1, SCTP_Config), + {remote_port, Remote_Port} = lists:keyfind(remote_port, 1, SCTP_Config), + Remote = #sigtran_peer{ip = Remote_IP, port = Remote_Port}, + {asp_id, Asp_ID} = lists:keyfind(asp_id, 1, M3UA_Config), + {route_ctx, Route_CTX} = lists:keyfind(route_ctx, 1, M3UA_Config), + {net_appearance, Net_Appearance} = lists:keyfind(net_appearance, 1, M3UA_Config), + Link = #sigtran_link{type = m3ua, name = "test_link", linkset_name = "test_linkset", + sls = 0, local = Local, remote = Remote, asp_id = Asp_ID, + route_ctx = Route_CTX, net_app = Net_Appearance}, + {ok, M3uaPid} = ss7_link_m3ua:start_link(Link), + %~ sys:trace(ss7_link_m3ua, ?TRACE), + %~ sys:trace(m3ua_core, ?TRACE), + % instantiate SCCP routing instance + {network_ind, Network_Ind} = lists:keyfind(network_ind, 1, M3UA_Config), + {ok, ScrcPid} = sccp_scrc:start_link([{mtp_tx_action, {callback_fn, fun scrc_tx_to_mtp/2, M3uaPid}}, + {ni, Network_Ind}]), + sys:trace(sccp_scrc, ?TRACE), + {ok, _SccpPid} = sccp_user:start_link(), + sys:trace(sccp_user, ?TRACE), + io:format("Waiting for M3UA link ...~n"), + wait_for_link(Link), + #loop_dat{m3ua_pid = M3uaPid, scrc_pid = ScrcPid, ss7links_pid = SS7linksPid, ss7routes_pid = SS7routesPid, link = Link, + local_pc = Local_PC, remote_pc = Remote_PC, gt_local = GT_Local, gt_hlr = GT_Hlr, gt_vlr = GT_Vlr, gt_msc = GT_Msc, + gt_sgsn = GT_Sgsn, gt_gmsc = GT_Gmsc, gt_smsc = GT_Smsc, msisdn = Msisdn_enc, imsi = hex:hexstr_to_bin(Imsi), scenter = SCenter_enc, fnumber = FNumber_enc}. + +wait_for_link(Link) -> + case ss7_link_m3ua:get_link_state(Link) of + {ok, down} -> + io:format("Link not ready, sleeping...~n"), + timer:sleep(100), + wait_for_link(Link); + {ok, active} -> + {ok}; + _ -> + {error} + end. + +handle_cast({test_hlr}, L) -> + io:format("Testing HLR~n"), + {noreply, map_tests:test_hlr(L)}; + +handle_cast({test_msc}, L) -> + io:format("Testing MSC~n"), + {noreply, map_tests:test_msc(L)}; + +handle_cast({test_smsc}, L) -> + io:format("Testing SMSC~n"), + {noreply, map_tests:test_smsc(L)}. + +handle_call(_, _From, L) -> + {ok, [], L}. + +test_hlr() -> + gen_server:cast(?MODULE, {test_hlr}). + +test_msc() -> + gen_server:cast(?MODULE, {test_msc}). + +test_smsc() -> + gen_server:cast(?MODULE, {test_smsc}). + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +handle_info(Info, S) -> + error_logger:error_report(["unknown handle_info", + {module, ?MODULE}, + {info, Info}, {state, S}]), + {noreply, S}. + +terminate(Reason, _S) -> + io:format("terminating ~p with reason ~p", [?MODULE, Reason]), + ok. + +scrc_tx_to_mtp(Prim, Args) -> + M3uaPid = Args, + gen_fsm:send_event(M3uaPid, Prim). + diff --git a/src/ss7MAPer.hrl b/src/ss7MAPer.hrl new file mode 100644 index 0000000..ee3894b --- /dev/null +++ b/src/ss7MAPer.hrl @@ -0,0 +1,29 @@ +% Number encoding Definitions + +-define(NUMBER_EXTENSION_NONE, 1). +-define(NUMBER_NATURE_INTERNATIONAL, 1). +-define(NUMBER_PLAN_ISDN, 1). +-define(NUMBER_LAND_MOBILE, 6). + +-define(TRACE, false). + +-record(loop_dat, { + scrc_pid, + m3ua_pid, + ss7links_pid, + ss7routes_pid, + link, + local_pc, + remote_pc, + gt_local, + gt_hlr, + gt_vlr, + gt_msc, + gt_sgsn, + gt_gmsc, + gt_smsc, + msisdn, + imsi, + scenter, + fnumber + }). diff --git a/src/ss7MAPer_app.erl b/src/ss7MAPer_app.erl new file mode 100644 index 0000000..3dc2500 --- /dev/null +++ b/src/ss7MAPer_app.erl @@ -0,0 +1,12 @@ +-module(ss7MAPer_app). +-author('Daniel Mende '). + +-behaviour(application). + +-export([start/2, stop/1]). + +start(_Type, Configfile) -> + ss7MAPer_sup:start_link(Configfile). + +stop(_State) -> + ok. diff --git a/src/ss7MAPer_sup.erl b/src/ss7MAPer_sup.erl new file mode 100644 index 0000000..915effc --- /dev/null +++ b/src/ss7MAPer_sup.erl @@ -0,0 +1,34 @@ +-module(ss7MAPer_sup). +-author('Daniel Mende '). + +-behaviour(supervisor). + +%% API +-export([start_link/1]). + +%% Supervisor callbacks +-export([init/1]). + +%% Helper macro for declaring children of supervisor +%~ -define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}). + +%% =================================================================== +%% API functions +%% =================================================================== + +start_link(Configfile) -> + supervisor:start_link(?MODULE, [Configfile]). + +%% =================================================================== +%% Supervisor callbacks +%% =================================================================== + +init(Configfile) -> + SupFlags = #{strategy => one_for_one, intensity => 1, period => 5}, + ChildSpecs = [#{id => ss7MAPer, + start => {ss7MAPer, start_link, Configfile}, + restart => permanent, + shutdown => brutal_kill, + type => worker, + modules => [ss7MAPer]}], + {ok, {SupFlags, ChildSpecs}}. diff --git a/src/ss7_helper.erl b/src/ss7_helper.erl new file mode 100644 index 0000000..194cbad --- /dev/null +++ b/src/ss7_helper.erl @@ -0,0 +1,53 @@ +-module(ss7_helper). +-author('Daniel Mende '). + +-export([encode_phonenumber/4, + decode_phonenumber/1, + encode_msisdn/4, + decode_imsi/1, + remove_firstN/2, + tup2bin/1]). + +decode_imsi(<<>>) -> + []; +decode_imsi(Imsi) -> + <> = Imsi, + Dec = decode_imsi(Rest), + if + First==15 -> lists:append([Second], Dec); + true -> lists:append([Second,First], Dec) + end. + +%% =================================================================== +%% Phone Number helper +%% =================================================================== + +encode_phonenumber(Extension, NatureOfNumber, NumberPlan, Number) -> + {EncNumber, Digits} = encode_phonenumber(Number), + <>. +encode_phonenumber([First,Second|Tail]) -> + {EncNumber, Digits} = encode_phonenumber(Tail), + {<>, Digits + 2}; +encode_phonenumber([Last]) -> + {<<15:4, Last:4>>, 1}; +encode_phonenumber([]) -> + {<<>>, 0}. + +decode_phonenumber(<<_Extension:1, _NatureOfNumber:1, _NumberPlan:4, Number/binary>>) -> + decode_imsi(Number). + +encode_msisdn(Extension, NatureOfNumber, NumberPlan, Number) -> + {EncNumber, _} = encode_phonenumber(Number), + <>. + +%% =================================================================== +%% List helper +%% =================================================================== + +remove_firstN(_, []) -> []; +remove_firstN(1, [_|T]) -> T; +remove_firstN(N, [_|T]) -> remove_firstN(N-1, T). + + +tup2bin(Tupel) -> + binary:list_to_bin([element(I,Tupel) || I <- lists:seq(1,tuple_size(Tupel))]). diff --git a/src/ss7test.app.src b/src/ss7test.app.src deleted file mode 100644 index cb8c804..0000000 --- a/src/ss7test.app.src +++ /dev/null @@ -1,12 +0,0 @@ -{application, ss7test, - [ - {description, ""}, - {vsn, "1"}, - {registered, []}, - {applications, [ - kernel, - stdlib - ]}, - {mod, { ss7test_app, ["./config"]}}, - {env, []} - ]}. diff --git a/src/ss7test_app.erl b/src/ss7test_app.erl deleted file mode 100644 index 3b81b4b..0000000 --- a/src/ss7test_app.erl +++ /dev/null @@ -1,555 +0,0 @@ --module(ss7test_app). --author('Daniel Mende '). - --behaviour(application). - -%% Application callbacks --export([start/2, stop/1]). - --compile([export_all]). % for debugging - --include_lib("osmo_ss7/include/osmo_util.hrl"). --include_lib("osmo_ss7/include/osmo_ss7.hrl"). --include_lib("osmo_ss7/include/m3ua.hrl"). --include_lib("osmo_ss7/include/sccp.hrl"). --include_lib("osmo_ss7/include/isup.hrl"). --include_lib("osmo_map/src/tcap_asn.hrl"). --include("ss7test_app.hrl"). - --define(TRACE, false). - --record(loop_dat, { - scrc_pid, - m3ua_pid, - ss7links_pid, - ss7routes_pid, - link, - local_pc, - remote_pc, - gt_local, - gt_hlr, - gt_vlr, - gt_msc, - gt_sgsn, - msisdn, - imsi, - scenter, - fnumber - }). - -%% change routing context in m3ua_code.erl => fixed -%% add pointcode to sccp in sccp_codec.erl -%% change network indicator in sccp_scrc.erl => fixed - - -%% =================================================================== -%% Application callbacks -%% =================================================================== - -start(_, Configfile) -> - LoopDat = init(Configfile), - spawn(ss7test_app, loop, [LoopDat]). - -stop(_State) -> - ok. - -%% =================================================================== - -init(Configfile) -> - Config = case file:consult(Configfile) of - {ok, C} -> - C; - {error, E} -> - io:fwrite("\e[91;1mError reading config file ~p:~n~p~n\e[39;49;0m", [Configfile, E]), - exit(config_error) - end, - {sctp, SCTP_Config} = lists:keyfind(sctp, 1, Config), - {m3ua, M3UA_Config} = lists:keyfind(m3ua, 1, Config), - {sccp, Sccp} = lists:keyfind(sccp, 1, Config), - {target, Target} = lists:keyfind(target, 1, Config), - {gt_local, GT_Local} = lists:keyfind(gt_local, 1, Sccp), - {gt_hlr, GT_Hlr} = lists:keyfind(gt_hlr, 1, Target), - {gt_vlr, GT_Vlr} = lists:keyfind(gt_vlr, 1, Target), - {gt_msc, GT_Msc} = lists:keyfind(gt_msc, 1, Target), - {gt_sgsn, GT_Sgsn} = lists:keyfind(gt_sgsn, 1, Target), - {msisdn, Msisdn} = lists:keyfind(msisdn, 1, Target), - {imsi, Imsi} = lists:keyfind(imsi, 1, Target), - Msisdn_enc = ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, - ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, - Msisdn), - {service_center, SCenter} = lists:keyfind(service_center, 1, Target), - SCenter_enc = ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, - ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, - SCenter), - {forward_number, FNumber} = lists:keyfind(forward_number, 1, Target), - FNumber_enc = ss7test_helper:encode_msisdn(?NUMBER_EXTENSION_NONE, - ?NUMBER_NATURE_INTERNATIONAL, ?NUMBER_PLAN_ISDN, - FNumber), - % start link server and create linkset - {ok, SS7linksPid} = ss7_links:start_link(), - sys:trace(ss7_links, ?TRACE), - {local_pc, Local_PC} = lists:keyfind(local_pc, 1, M3UA_Config), - {remote_pc, Remote_PC} = lists:keyfind(remote_pc, 1, M3UA_Config), - ok = ss7_links:register_linkset(Local_PC, Remote_PC, "test_linkset"), - %start route server and add route - {ok, SS7routesPid} = ss7_routes:start_link(), - ok = ss7_routes:create_route(Remote_PC, 16#ffff, "test_linkset"), - % create m3ua link - {local_ip, Local_IP} = lists:keyfind(local_ip, 1, SCTP_Config), - {local_port, Local_Port} = lists:keyfind(local_port, 1, SCTP_Config), - Local = #sigtran_peer{ip = Local_IP, port = Local_Port}, - {remote_ip, Remote_IP} = lists:keyfind(remote_ip, 1, SCTP_Config), - {remote_port, Remote_Port} = lists:keyfind(remote_port, 1, SCTP_Config), - Remote = #sigtran_peer{ip = Remote_IP, port = Remote_Port}, - {asp_id, Asp_ID} = lists:keyfind(asp_id, 1, M3UA_Config), - {route_ctx, Route_CTX} = lists:keyfind(route_ctx, 1, M3UA_Config), - {net_appearance, Net_Appearance} = lists:keyfind(net_appearance, 1, M3UA_Config), - Link = #sigtran_link{type = m3ua, name = "test_link", linkset_name = "test_linkset", - sls = 0, local = Local, remote = Remote, asp_id = Asp_ID, - route_ctx = Route_CTX, net_app = Net_Appearance}, - {ok, M3uaPid} = ss7_link_m3ua:start_link(Link), - % instantiate SCCP routing instance - {network_ind, Network_Ind} = lists:keyfind(network_ind, 1, M3UA_Config), - {ok, ScrcPid} = sccp_scrc:start_link([{mtp_tx_action, {callback_fn, fun scrc_tx_to_mtp/2, M3uaPid}}, - {ni, Network_Ind}]), - sys:trace(sccp_scrc, ?TRACE), - {ok, _SccpPid} = sccp_user:start_link(), - sys:trace(sccp_user, ?TRACE), - io:format("Waiting for M3UA link comming up...~n"), - wait_for_link(Link), - #loop_dat{m3ua_pid = M3uaPid, scrc_pid = ScrcPid, ss7links_pid = SS7linksPid, ss7routes_pid = SS7routesPid, link = Link, - local_pc = Local_PC, remote_pc = Remote_PC, gt_local = GT_Local, gt_hlr = GT_Hlr, gt_vlr = GT_Vlr, gt_msc = GT_Msc, - gt_sgsn = GT_Sgsn, msisdn = Msisdn_enc, imsi = Imsi, scenter = SCenter_enc, fnumber = FNumber_enc}. - -wait_for_link(Link) -> - case ss7_link_m3ua:get_link_state(Link) of - {ok, down} -> - timer:sleep(100), - wait_for_link(Link); - {ok, active} -> - {ok}; - _ -> - {error} - end. - -loop(L) -> - receive - {sccp, Prim} -> - {primitive, 'N', 'UNITDATA', indication, Data} = Prim, - {sccp_msg, _, ProtData} = Data, - {user_data, _UserData} = lists:keyfind(user_data, 1, ProtData), - %~ io:format("Rx: ~p~n", [map:decode('MapSpecificPDUs', UserData)]), - loop(L); - {send, {Gts, {Lssn, Rssn}}, Data} -> - Tlssn = case Lssn of - hlr -> ?SCCP_SSN_HLR; - vlr -> ?SCCP_SSN_VLR; - msc -> ?SCCP_SSN_MSC; - sgsn -> ?SCCP_SSN_SGSN; - cap -> ?SCCP_SSN_CAP; - _ -> ?SCCP_SSN_UNKNOWN - end, - Trssn = case Rssn of - hlr -> ?SCCP_SSN_HLR; - vlr -> ?SCCP_SSN_VLR; - msc -> ?SCCP_SSN_MSC; - sgsn -> ?SCCP_SSN_SGSN; - cap -> ?SCCP_SSN_CAP; - _ -> ?SCCP_SSN_UNKNOWN - end, - send_tcap(L, Gts, {Tlssn, Trssn}, Data), - loop(L); - {test_hlr} -> - io:format("Testing HLR~n"), - test_hlr(L), - loop(L); - {link_state} -> - io:format("~p~n", [ss7_link_m3ua:get_link_state(L#loop_dat.link)]), - loop(L); - Stop -> - M3uaPid = L#loop_dat.m3ua_pid, - %~ ScrcPid = L#loop_dat.scrc_pid, - SS7linksPid = L#loop_dat.ss7links_pid, - %~ SS7routesPid = L#loop_dat.ss7routes_pid, - io:format("Received ~p~n", [Stop]), - sccp_user:stop(), - sccp_scrc:stop(), - %~ ss7_link_m3ua:stop(), - gen_server:cast(M3uaPid, stop), - ss7_routes:stop(), - %~ ss7_links:stop(), - gen_server:cast(SS7linksPid, stop), - exit(stop_received) - end. - -test_hlr(L) -> - LocalSsn = ?SCCP_SSN_MSC, - ok = sccp_user:bind_ssn(LocalSsn), - Gts = {L#loop_dat.gt_local, L#loop_dat.gt_hlr}, - test_sri(Gts, L), - test_srifs(Gts, L), - L2 = test_si(Gts, L), - test_sai(Gts, L2, 100), - test_sai(Gts, L2, 10), - test_sai(Gts, L2, 5), - test_rss(Gts, L2), - test_ess(Gts, L2), - test_ul(Gts, L2), - test_ati(Gts, L2), - test_pms(Gts, L2), - ok = sccp_user:unbind_ssn(LocalSsn, undefined). - -test_sri(Gts, L) -> - %~ ======== - %~ sendRoutingInfo - %~ ======== - io:format("~n\e[93;1m# Testing sendRoutingInfo...\n\e[39;49;0m"), - send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_sendRoutingInfo(L#loop_dat.msisdn, L#loop_dat.gt_local)), - receive - {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> - case decode_tcap(Data) of - {ok, Results} -> - io:format("\e[97;1mGot answer for sendRoutingInfo~n~w~n\e[39;49;0m", [Results]), - case Results of - [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> - io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); - [{basicROS, - {returnResult, - {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', - {present,1},{'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', - {local,22},_}}}}|_] -> - io:format("\e[91;1mReceived SendRoutingInfoRes~n\e[39;49;0m"); - _ -> - io:format("\e[93;1mNo Error.~n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError decoding SendRoutingInfo\n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError no data received for SendRoutingInfo\n\e[39;49;0m") - after 2000 -> - io:format("\e[91;1mError timeout on receiving SendRoutingInfo\n\e[39;49;0m") - end, - L. - -test_srifs(Gts, L) -> - %~ ======== - %~ sendRoutingInfoForSM - %~ ======== - io:format("~n\e[93;1m# Testing sendRoutingInfoForSM...\n\e[39;49;0m"), - send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_sendRoutingInfoForSM(L#loop_dat.msisdn, L#loop_dat.scenter)), - receive - {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> - case decode_tcap(Data) of - {ok, Results} -> - io:format("\e[97;1mGot answer for sendRoutingInfoForSM\n~w\n\e[39;49;0m", [Results]), - case Results of - [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}|_] -> - case {Present, Local} of - {1, 6} -> - io:format("\e[91;1mSubscriber is absent~n\e[39;49;0m"); - _ -> - io:format("\e[92;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]) - end; - [{basicROS, - {returnResult, - {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', - {present,1},{'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', - {local,45}, Res}}}}|_] -> - {'RoutingInfoForSM-Res',_, - {'LocationInfoWithLMSI',Loc,_,_,_,_},_,_} = Res, - io:format("\e[91;1mReceived routingInfoForSM, Mobile Station ~w", [ss7test_helper:decode_phonenumber(Loc)]); - _ -> - io:format("\e[93;1mNo Error.~n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError decoding SendRoutingInfoForSM\n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError no data received for SendRoutingInfoForSM\n\e[39;49;0m") - after 2000 -> - io:format("\e[91;1mError timeout on receiving SendRoutingInfoForSM\n\e[39;49;0m") - end, - L. - -test_si(Gts, L) -> - %~ ======== - %~ sendImsi - %~ ======== - io:format("~n\e[93;1m# Testing sendImsi...\n\e[39;49;0m"), - send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_sendImsi(L#loop_dat.msisdn)), - receive - {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> - case decode_tcap(Data) of - {ok, Results} -> - io:format("\e[97;1mGot answer for sendImsi\n~w\n\e[39;49;0m", [Results]), - case Results of - [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> - io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]), - L; - [{basicROS, - {returnResult, - {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', - {present,1}, - {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', - {local,58}, - Imsi }}}}|_] -> - io:format("\e[91;1mReceived IMSI ~w~n\e[39;49;0m", [ss7test_helper:decode_imsi(Imsi)]), - L#loop_dat{imsi = Imsi} - end; - _-> - io:format("\e[91;1mError decoding sendImsi\n\e[39;49;0m"), - L - end; - _-> - io:format("\e[91;1mError no data received for sendImsi\n\e[39;49;0m"), - L - after 2000 -> - io:format("\e[91;1mError timeout on receiving sendImsi\n\e[39;49;0m"), - L - end. - -test_sai(Gts, L, Nr) -> - %~ ======== - %~ sendAuthenticationInfo - %~ ======== - io:format("~n\e[93;1m# Testing sendAuthenticationInfo...\n\e[39;49;0m"), - send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_sendAuthenticationInfo(L#loop_dat.imsi, Nr)), - receive - {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> - case decode_tcap(Data) of - {ok, Results} -> - io:format("\e[97;1mGot answer for sendAuthenticationInfo\n~w\n\e[39;49;0m", [Results]), - case Results of - [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> - io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); - [{basicROS, {reject, _}}|_] -> - if - Nr>5 -> io:format("\e[92;1mAsked for ~w (>5) vectors, got rejected~n\e[39;49;0m", [Nr]); - Nr<6 -> io:format("\e[91;1mAsked for ~w (<=5) vectors, got rejected~n\e[39;49;0m", [Nr]) - end; - [{basicROS, - {returnResult, - {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', - {present,1}, {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', - {local,56}, {'SendAuthenticationInfoRes', - {quintupletList,ResList},_,_}}}}}|_] -> - NrRes = length(ResList), - if - Nr>5 -> - if - NrRes>5 -> io:format("\e[91;1mAsked for ~w vectors, got ~w (>5) result vectors~n\e[39;49;0m", [Nr,NrRes]) - end; - Nr<6 -> - if - NrRes==Nr -> io:format("\e[92;1mAsked for ~w vectors, got ~w (=~w) result vectors~n\e[39;49;0m", [Nr,NrRes,Nr]); - true -> io:format("\e[93;1mAsked for ~w vectors, got ~w (!=~w) result vectors~n\e[39;49;0m", [Nr,NrRes,Nr]) - end - end; - _ -> - io:format("\e[93;1mNo Error.~n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError decoding sendAuthenticationInfo\n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError no data received for sendAuthenticationInfo\n\e[39;49;0m") - after 2000 -> - io:format("\e[91;1mError timeout on receiving sendAuthenticationInfo\n\e[39;49;0m") - end, - L. - -test_rss(Gts, L) -> - %~ ======== - %~ registerSS - %~ ======== - io:format("~n\e[93;1m# Testing registerSS...\n\e[39;49;0m"), - send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_registerSS(ss7test_helper:decode_imsi(L#loop_dat.imsi), L#loop_dat.gt_vlr, L#loop_dat.fnumber)), - receive - {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> - case decode_tcap(Data) of - {ok, Results} -> - io:format("\e[97;1mGot answer for registerSS\n~w\n\e[39;49;0m", [Results]), - case Results of - [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> - io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); - [{basicROS, - {returnResult, - {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', - {present,1}, {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', - {local,10},_}}}}|_] -> - io:format("\e[91;1mReceived forwardingInfo, registerSS is working~n\e[39;49;0m"); - _ -> - io:format("\e[93;1mNo Error.~n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError decoding registerSS\n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError no data received for registerSS\n\e[39;49;0m") - after 2000 -> - io:format("\e[91;1mError timeout on receiving registerSS\n\e[39;49;0m") - end, - L. - -test_ess(Gts, L) -> - %~ ======== - %~ eraseSS - %~ ======== - io:format("~n\e[93;1m# Testing eraseSS...\n\e[39;49;0m"), - send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_eraseSS(ss7test_helper:decode_imsi(L#loop_dat.imsi), L#loop_dat.gt_vlr)), - receive - {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> - case decode_tcap(Data) of - {ok, Results} -> - io:format("\e[97;1mGot answer for eraseSS\n~w\n\e[39;49;0m", [Results]), - case Results of - [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> - io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); - [{basicROS, - {returnResult, - {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', - {present,1}, {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', - {local,11},_}}}}|_] -> - io:format("\e[91;1mReceived forwardingInfo, eraseSS is working~n\e[39;49;0m"); - _ -> - io:format("\e[93;1mNo Error.~n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError decoding eraseSS\n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError no data received for eraseSS\n\e[39;49;0m") - after 2000 -> - io:format("\e[91;1mError timeout on receiving eraseSS\n\e[39;49;0m") - end, - L. - -test_ul(Gts, L) -> - %~ ======== - %~ updateLocation - %~ ======== - io:format("~n\e[93;1m# Testing updateLocation...\n\e[39;49;0m"), - send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_updateLocation(L#loop_dat.imsi, L#loop_dat.gt_local, L#loop_dat.gt_local)), - receive - {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> - case decode_tcap(Data) of - {ok, Results} -> - io:format("\e[97;1mGot answer for updateLocation\n~w\n\e[39;49;0m", [Results]), - case Results of - [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> - io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); - [{basicROS,{invoke,{'MapSpecificPDUs_continue_components_SEQOF_basicROS_invoke',{present,2},asn1_NOVALUE,{local,7},_}}}|_] -> - io:format("\e[91;1mReceived insertSubscriberData, updateLocation is working~n\e[39;49;0m"); - _ -> - io:format("\e[93;1mNo Error.~n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError decoding updateLocation\n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError no data received for updateLocation\n\e[39;49;0m") - after 2000 -> - io:format("\e[91;1mError timeout on receiving updateLocation\n\e[39;49;0m") - end, - L. - -test_ati(Gts, L) -> - %~ ======== - %~ anyTimeInterrogation - %~ ======== - io:format("~n\e[93;1m# Testing anyTimeInterrogation...\n\e[39;49;0m"), - send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_anyTimeInerrogation(L#loop_dat.imsi, L#loop_dat.gt_local)), - receive - {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> - case decode_tcap(Data) of - {ok, Results} -> - io:format("\e[97;1mGot answer for anyTimeInerrogation\n~w\n\e[39;49;0m", [Results]), - case Results of - [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> - case {Present, Local} of - {1, 49} -> - io:format("\e[92;1manyTimeInterrogation is forbidden~n\e[39;49;0m"); - _ -> - io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]) - end; - _ -> - io:format("\e[93;1mNo Error.~n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError decoding anyTimeInerrogation\n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError no data received for anyTimeInerrogation\n\e[39;49;0m") - after 2000 -> - io:format("\e[91;1mError timeout on receiving anyTimeInerrogation\n\e[39;49;0m") - end, - L. - -test_pms(Gts, L) -> - %~ ======== - %~ purgeMS - %~ ======== - io:format("~n\e[93;1m# Testing purgeMS...\n\e[39;49;0m"), - send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_purgeMs(L#loop_dat.imsi, L#loop_dat.gt_local)), - receive - {sccp, {primitive, 'N', 'UNITDATA', indication, Data}} -> - case decode_tcap(Data) of - {ok, Results} -> - io:format("\e[97;1mGot answer for purgeMs\n~w\n\e[39;49;0m", [Results]), - case Results of - [{basicROS, {returnError, {_, {present, Present}, {local, Local}, _}}}] -> - io:format("\e[91;1mReceived Error: Present ~w, Local ~w~n\e[39;49;0m", [Present, Local]); - [{basicROS, - {returnResult, - {'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult', - {present,1},{'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result', - {local,67},_}}}}|_] -> - io:format("\e[91;1mReceived purgeMS-Res, purgeMS is working~n\e[39;49;0m"); - _ -> - io:format("\e[93;1mNo Error.~n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError decoding purgeMs\n\e[39;49;0m") - end; - _-> - io:format("\e[91;1mError no data received for purgeMs\n\e[39;49;0m") - after 2000 -> - io:format("\e[91;1mError timeout on receiving purgeMs\n\e[39;49;0m") - end, - L. - -scrc_tx_to_mtp(Prim, Args) -> - M3uaPid = Args, - gen_fsm:send_event(M3uaPid, Prim). - -send_tcap(L, {Lgt, Rgt}, {Sssn, Dssn}, PDU) -> - CallingP = #sccp_addr{ssn = Sssn, point_code = L#loop_dat.local_pc, - global_title = #global_title{gti = ?SCCP_GTI_TT_NP_ENC_NAT, trans_type = ?SCCP_GTI_NO_GT, - encoding = 0, numbering_plan = 1, phone_number = Lgt, - nature_of_addr_ind = ?ISUP_ADDR_NAT_INTERNATIONAL}}, - CalledP = #sccp_addr{ssn = Dssn, point_code = L#loop_dat.remote_pc, - global_title = #global_title{gti = ?SCCP_GTI_TT_NP_ENC_NAT, trans_type = ?SCCP_GTI_NO_GT, - encoding = 0, numbering_plan = 1, phone_number = Rgt, - nature_of_addr_ind = ?ISUP_ADDR_NAT_INTERNATIONAL}}, - Opts = [{protocol_class, {1, 8}}, {called_party_addr, CalledP}, - {calling_party_addr, CallingP}, {user_data, PDU}], - gen_fsm:send_event(L#loop_dat.scrc_pid, osmo_util:make_prim('N','UNITDATA',request,Opts)). - -decode_tcap(Data) -> - {sccp_msg, _, ProtData} = Data, - {user_data, UserData} = lists:keyfind(user_data, 1, ProtData), - {ok, TcapData} = map:decode('MapSpecificPDUs', UserData), - case TcapData of - {'end', {'MapSpecificPDUs_end', _Transaction, % <<1,1,0,0>>, - {'EXTERNAL', - {0,0,17,773,1,1,1}, - _,_, %asn1_NOVALUE,asn1_NOVALUE, - _Dialog}, Results}} -> {}; - {continue, {'MapSpecificPDUs_continue', _STransaction, _Transaction, - {'EXTERNAL', - {0,0,17,773,1,1,1}, - _,_, %asn1_NOVALUE,asn1_NOVALUE, - _Dialog}, Results}} -> {} - end, - {ok, Results}. diff --git a/src/ss7test_app.hrl b/src/ss7test_app.hrl deleted file mode 100644 index 49703c0..0000000 --- a/src/ss7test_app.hrl +++ /dev/null @@ -1,6 +0,0 @@ -% Number encoding Definitions - --define(NUMBER_EXTENSION_NONE, 1). --define(NUMBER_NATURE_INTERNATIONAL, 1). --define(NUMBER_PLAN_ISDN, 1). --define(NUMBER_LAND_MOBILE, 6). diff --git a/src/ss7test_helper.erl b/src/ss7test_helper.erl deleted file mode 100644 index e66ca15..0000000 --- a/src/ss7test_helper.erl +++ /dev/null @@ -1,53 +0,0 @@ --module(ss7test_helper). --author('Daniel Mende '). - --export([encode_phonenumber/4, - decode_phonenumber/1, - encode_msisdn/4, - decode_imsi/1, - remove_firstN/2, - tup2bin/1]). - -decode_imsi(<<>>) -> - []; -decode_imsi(Imsi) -> - <> = Imsi, - Dec = decode_imsi(Rest), - if - First==15 -> lists:append([Second], Dec); - true -> lists:append([Second,First], Dec) - end. - -%% =================================================================== -%% Phone Number helper -%% =================================================================== - -encode_phonenumber(Extension, NatureOfNumber, NumberPlan, Number) -> - {EncNumber, Digits} = encode_phonenumber(Number), - <>. -encode_phonenumber([First,Second|Tail]) -> - {EncNumber, Digits} = encode_phonenumber(Tail), - {<>, Digits + 2}; -encode_phonenumber([Last]) -> - {<<15:4, Last:4>>, 1}; -encode_phonenumber([]) -> - {<<>>, 0}. - -decode_phonenumber(<<_Extension:1, _NatureOfNumber:1, _NumberPlan:4, Number/binary>>) -> - decode_imsi(Number). - -encode_msisdn(Extension, NatureOfNumber, NumberPlan, Number) -> - {EncNumber, _} = encode_phonenumber(Number), - <>. - -%% =================================================================== -%% List helper -%% =================================================================== - -remove_firstN(_, []) -> []; -remove_firstN(1, [_|T]) -> T; -remove_firstN(N, [_|T]) -> remove_firstN(N-1, T). - - -tup2bin(Tupel) -> - binary:list_to_bin([element(I,Tupel) || I <- lists:seq(1,tuple_size(Tupel))]). diff --git a/src/ss7test_sup.erl b/src/ss7test_sup.erl deleted file mode 100644 index 1b47715..0000000 --- a/src/ss7test_sup.erl +++ /dev/null @@ -1,27 +0,0 @@ --module(ss7test_sup). - --behaviour(supervisor). - -%% API --export([start_link/0]). - -%% Supervisor callbacks --export([init/1]). - -%% Helper macro for declaring children of supervisor --define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}). - -%% =================================================================== -%% API functions -%% =================================================================== - -start_link() -> - supervisor:start_link({local, ?MODULE}, ?MODULE, []). - -%% =================================================================== -%% Supervisor callbacks -%% =================================================================== - -init([]) -> - {ok, { {one_for_one, 5, 10}, []} }. - diff --git a/src/tcap.erl b/src/tcap.erl new file mode 100644 index 0000000..6f1a515 --- /dev/null +++ b/src/tcap.erl @@ -0,0 +1,41 @@ +-module(tcap). +-author('Daniel Mende '). + +-include_lib("osmo_ss7/include/sccp.hrl"). +-include_lib("osmo_ss7/include/isup.hrl"). +-include("ss7MAPer.hrl"). + +-export([send_tcap/4, decode_tcap/1]). + +send_tcap(L, {Lgt, Rgt}, {Sssn, Dssn}, PDU) -> + CallingP = #sccp_addr{ssn = Sssn, point_code = L#loop_dat.local_pc, + global_title = #global_title{gti = ?SCCP_GTI_TT_NP_ENC_NAT, trans_type = ?SCCP_GTI_NO_GT, + encoding = 0, numbering_plan = 1, phone_number = Lgt, + nature_of_addr_ind = ?ISUP_ADDR_NAT_INTERNATIONAL}}, + CalledP = #sccp_addr{ssn = Dssn, point_code = L#loop_dat.remote_pc, + global_title = #global_title{gti = ?SCCP_GTI_TT_NP_ENC_NAT, trans_type = ?SCCP_GTI_NO_GT, + encoding = 0, numbering_plan = 1, phone_number = Rgt, + nature_of_addr_ind = ?ISUP_ADDR_NAT_INTERNATIONAL}}, + Opts = [{protocol_class, {1, 8}}, {called_party_addr, CalledP}, + {calling_party_addr, CallingP}, {user_data, PDU}], + %~ io:format("Sending N-UNITDATA.req to SCRC~n"), + %~ io:format("Link is in state ~p~n", [sys:get_status(L#loop_dat.scrc_pid)]), + gen_fsm:send_event(L#loop_dat.scrc_pid, osmo_util:make_prim('N','UNITDATA',request,Opts)). + +decode_tcap(Data) -> + {sccp_msg, _, ProtData} = Data, + {user_data, UserData} = lists:keyfind(user_data, 1, ProtData), + {ok, TcapData} = map:decode('MapSpecificPDUs', UserData), + case TcapData of + {'end', {'MapSpecificPDUs_end', _Transaction, % <<1,1,0,0>>, + {'EXTERNAL', + {0,0,17,773,1,1,1}, + _,_, %asn1_NOVALUE,asn1_NOVALUE, + _Dialog}, Results}} -> {}; + {continue, {'MapSpecificPDUs_continue', _STransaction, _Transaction, + {'EXTERNAL', + {0,0,17,773,1,1,1}, + _,_, %asn1_NOVALUE,asn1_NOVALUE, + _Dialog}, Results}} -> {} + end, + {ok, Results}. diff --git a/ss7test.iml b/ss7test.iml deleted file mode 100644 index 7626f17..0000000 --- a/ss7test.iml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file -- cgit v1.2.3