diff options
author | Daniel <0xc0decafe@users.noreply.github.com> | 2016-10-05 12:42:59 +0200 |
---|---|---|
committer | Daniel <0xc0decafe@users.noreply.github.com> | 2016-10-05 12:42:59 +0200 |
commit | e7d5812d17e1165492ad342c016c80bad24ae9aa (patch) | |
tree | 3c67a47eb255f04f831f535848658f20d9493480 | |
parent | b99ffff4982e19424fc78abadd57100a8032bdad (diff) |
Structure changed in regard to erlang OTP. Added binary release.
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | README.md | 30 | ||||
-rw-r--r-- | config.example | 16 | ||||
-rwxr-xr-x | prepare_n_build.sh | 5 | ||||
-rw-r--r-- | rebar.config | 1 | ||||
-rw-r--r-- | rel/reltool.config | 46 | ||||
-rw-r--r-- | releases/ss7MAPer-v0.2_linux_x64.tar.bz2 | bin | 0 -> 21840063 bytes | |||
-rw-r--r-- | src/map_msgs.erl | 99 | ||||
-rw-r--r-- | src/map_tests.erl (renamed from src/ss7test_app.erl) | 445 | ||||
-rw-r--r-- | src/ss7MAPer.app.src | 13 | ||||
-rw-r--r-- | src/ss7MAPer.erl | 153 | ||||
-rw-r--r-- | src/ss7MAPer.hrl | 29 | ||||
-rw-r--r-- | src/ss7MAPer_app.erl | 12 | ||||
-rw-r--r-- | src/ss7MAPer_sup.erl | 34 | ||||
-rw-r--r-- | src/ss7_helper.erl (renamed from src/ss7test_helper.erl) | 2 | ||||
-rw-r--r-- | src/ss7test.app.src | 12 | ||||
-rw-r--r-- | src/ss7test_app.hrl | 6 | ||||
-rw-r--r-- | src/ss7test_sup.erl | 27 | ||||
-rw-r--r-- | src/tcap.erl | 41 | ||||
-rw-r--r-- | ss7test.iml | 20 |
20 files changed, 626 insertions, 368 deletions
@@ -5,6 +5,7 @@ deps *.plt erl_crash.dump ebin -rel/example_project +rel/ss7MAPer +rel/files .concrete/DEV_MODE .rebar @@ -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 Binary files differnew file mode 100644 index 0000000..da8bb3e --- /dev/null +++ b/releases/ss7MAPer-v0.2_linux_x64.tar.bz2 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 <mail@c0decafe.de>'). -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/ss7test_app.erl b/src/map_tests.erl index 3b81b4b..b3fddb9 100644 --- a/src/ss7test_app.erl +++ b/src/map_tests.erl @@ -1,186 +1,14 @@ --module(ss7test_app). +-module(map_tests). -author('Daniel Mende <mail@c0decafe.de>'). --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 -%% =================================================================== +-include("ss7MAPer.hrl"). -start(_, Configfile) -> - LoopDat = init(Configfile), - spawn(ss7test_app, loop, [LoopDat]). +-export([test_hlr/1, test_msc/1, test_smsc/1]). -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. +%~ ========= +%~ HLR TESTS +%~ ========= test_hlr(L) -> LocalSsn = ?SCCP_SSN_MSC, @@ -197,17 +25,18 @@ test_hlr(L) -> test_ul(Gts, L2), test_ati(Gts, L2), test_pms(Gts, L2), - ok = sccp_user:unbind_ssn(LocalSsn, undefined). + 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"), - send_tcap(L, Gts, {?SCCP_SSN_MSC, ?SCCP_SSN_HLR}, map_msgs:create_sendRoutingInfo(L#loop_dat.msisdn, L#loop_dat.gt_local)), + 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 decode_tcap(Data) of + 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 @@ -237,10 +66,10 @@ 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)), + 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 decode_tcap(Data) of + 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 @@ -258,7 +87,7 @@ test_srifs(Gts, L) -> {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[91;1mReceived routingInfoForSM, Mobile Station ~w", [ss7_helper:decode_phonenumber(Loc)]); _ -> io:format("\e[93;1mNo Error.~n\e[39;49;0m") end; @@ -277,10 +106,10 @@ 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)), + 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 decode_tcap(Data) of + 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 @@ -294,7 +123,7 @@ test_si(Gts, L) -> {'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)]), + io:format("\e[91;1mReceived IMSI ~w~n\e[39;49;0m", [ss7_helper:decode_imsi(Imsi)]), L#loop_dat{imsi = Imsi} end; _-> @@ -314,10 +143,10 @@ 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)), + 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 decode_tcap(Data) of + 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 @@ -364,10 +193,10 @@ 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)), + 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 decode_tcap(Data) of + 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 @@ -397,10 +226,10 @@ 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)), + 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 decode_tcap(Data) of + 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 @@ -430,10 +259,10 @@ 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)), + 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 decode_tcap(Data) of + 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 @@ -459,10 +288,10 @@ 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)), + 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 decode_tcap(Data) of + 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 @@ -491,10 +320,10 @@ 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)), + 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 decode_tcap(Data) of + 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 @@ -519,37 +348,193 @@ test_pms(Gts, L) -> end, L. -scrc_tx_to_mtp(Prim, Args) -> - M3uaPid = Args, - gen_fsm:send_event(M3uaPid, Prim). +%~ ========= +%~ 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. -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)). +%~ ========== +%~ SMSC TESTS +%~ ========== -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}} -> {} +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, - {ok, Results}. + 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 <mail@c0decafe.de>'). + +-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 <mail@c0decafe.de>'). + +-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 <mail@c0decafe.de>'). + +-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/ss7test_helper.erl b/src/ss7_helper.erl index e66ca15..194cbad 100644 --- a/src/ss7test_helper.erl +++ b/src/ss7_helper.erl @@ -1,4 +1,4 @@ --module(ss7test_helper). +-module(ss7_helper). -author('Daniel Mende <mail@c0decafe.de>'). -export([encode_phonenumber/4, 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.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_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 <mail@c0decafe.de>'). + +-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 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="ERLANG_MODULE" version="4"> - <component name="FacetManager"> - <facet type="erlang" name="Erlang"> - <configuration /> - </facet> - </component> - <component name="NewModuleRootManager" inherit-compiler-output="false"> - <output url="file://$MODULE_DIR$/ebin" /> - <output-test url="file://$MODULE_DIR$/.eunit" /> - <exclude-output /> - <content url="file://$MODULE_DIR$"> - <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="module" module-name="osmo_ss7" /> - <orderEntry type="module" module-name="osmo_map" /> - </component> -</module>
\ No newline at end of file |