diff --git a/hlr/HLR_Tests.cfg b/hlr/HLR_Tests.cfg index 7416362db..1ab6e873d 100644 --- a/hlr/HLR_Tests.cfg +++ b/hlr/HLR_Tests.cfg @@ -12,6 +12,7 @@ [MODULE_PARAMETERS] +HLR_Tests.mp_hlr_supports_dgsm := true [MAIN_CONTROLLER] diff --git a/hlr/HLR_Tests.default b/hlr/HLR_Tests.default index 84d4ff390..2e9aac649 100644 --- a/hlr/HLR_Tests.default +++ b/hlr/HLR_Tests.default @@ -11,6 +11,11 @@ mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING; // | DEBUG_ENCDEC; *.VTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes" *.VTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes" *.VTY.PROMPT1 := "OsmoHLR> " +*.mDNS_UDP.debugging := "YES" +*.mDNS_UDP.localPort := "4266" +*.mDNS_UDP.localIPAddr := "239.192.23.42" +*.mDNS_UDP.broadcast := "enabled" +*.mDNS_UDP.reuseAddr := "enabled" [MODULE_PARAMETERS] Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoHLR"; diff --git a/hlr/HLR_Tests.ttcn b/hlr/HLR_Tests.ttcn index b59f86eab..c1cc12932 100644 --- a/hlr/HLR_Tests.ttcn +++ b/hlr/HLR_Tests.ttcn @@ -31,6 +31,10 @@ import from USSD_Helpers all; import from Osmocom_VTY_Functions all; import from TELNETasp_PortType all; +import from MSLookup_mDNS_Types all; +import from MSLookup_mDNS_Emulation all; +import from MSLookup_mDNS_Templates all; + type component test_CT extends CTRL_Adapter_CT { var IPA_Emulation_CT vc_IPA; var IPA_CCM_Parameters ccm_pars; @@ -43,6 +47,8 @@ type component test_CT extends CTRL_Adapter_CT { port TELNETasp_PT VTY; + var MSLookup_mDNS_Emulation_CT vc_MSLookup_mDNS; + timer g_Tguard := 10.0; }; @@ -53,6 +59,9 @@ modulepar { /* how many auth tuples are expected when IE ts_GSUP_IE_NUM_VECTORS_REQ is absent */ integer mp_default_num_auth_tuples := 5; + + /* drop after osmo-hlr release > 1.2.0 */ + boolean mp_hlr_supports_dgsm := true; }; type record HlrSubscrAud2G { @@ -80,6 +89,7 @@ type component HLR_ConnHdlr extends GSUP_ConnHdlr { timer g_Tguard := 10.0; var HLR_ConnHdlrPars g_pars; port TELNETasp_PT VTY; + port MSLookup_mDNS_PT mDNS; } type record HLR_ConnHdlrPars { @@ -116,6 +126,9 @@ function f_init_vty() runs on test_CT { map(self:VTY, system:VTY); f_vty_set_prompts(VTY); f_vty_transceive(VTY, "enable"); + if (mp_hlr_supports_dgsm) { + f_vty_config(VTY, "mslookup", "no mdns bind"); + } } private altstep as_Tguard() runs on test_CT { @@ -167,6 +180,11 @@ function f_init_gsup(charstring id, boolean legacy) runs on test_CT { } } +function f_init_mslookup() runs on test_CT { + vc_MSLookup_mDNS := MSLookup_mDNS_Emulation_CT.create; + vc_MSLookup_mDNS.start(MSLookup_mDNS_Emulation.f_main()); +} + function f_init(boolean legacy := true) runs on test_CT { /* activate default guard timer to ensure all tests eventually terminate */ @@ -175,6 +193,7 @@ function f_init(boolean legacy := true) runs on test_CT { f_init_gsup("HLR_Test", legacy); f_init_vty(); + f_init_mslookup(); f_ipa_ctrl_start(mp_hlr_ip, mp_hlr_ctrl_port); } @@ -186,6 +205,7 @@ function f_start_handler(void_fn fn, HLR_ConnHdlrPars pars) runs on test_CT retu vc_conn := HLR_ConnHdlr.create(id); connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT); connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC); + connect(vc_conn:mDNS, vc_MSLookup_mDNS:mDNS); vc_conn.start(f_handler_init(fn, id, pars)); return vc_conn; @@ -1511,6 +1531,66 @@ testcase TC_subscr_create_on_demand_sai() runs on test_CT { vc_conn.done; } +/* Send an mslookup mDNS request to the home HLR, asking about a service that is not "gsup.hlr". (Hence the "_other" in + * the test name, service "gsup.hlr" has different code paths, see related tests). */ +private function f_TC_MSLookup_mDNS_service_other_home() runs on HLR_ConnHdlr { + timer T; + var MSLookup_mDNS vl_rmsg; + var integer id := f_rnd_int(65535); /* mDNS packet ID */ + var hexstring msisdn := '49161'H & f_rnd_hexstring(7, 9); + var charstring domain := "sip.voice." & hex2str(msisdn) & ".msisdn.mdns.osmocom.org"; + + /* Create subscriber */ + g_pars.sub.msisdn := msisdn; + f_vty_subscr_create(VTY, g_pars.sub); + + /* Send mDNS query, expect timeout */ + mDNS.send(ts_MSLookup_mDNS_query(id, domain)); + T.start(1.0); + alt { + [] mDNS.receive(tr_MSLookup_mDNS_result_IPv4(id, domain, '42424242'O, 5060)) { + setverdict(fail, "OsmoHLR answered to mDNS query before subscriber did LU"); + } + [] mDNS.receive(MSLookup_mDNS:?) -> value vl_rmsg { + repeat; + } + [] T.timeout { + } + } + + /* Location update */ + f_perform_UL(g_pars.sub.imsi, msisdn, dom := OSMO_GSUP_CN_DOMAIN_CS); + + /* Send mDNS query again, expect result */ + mDNS.send(ts_MSLookup_mDNS_query(id, domain)); + T.start(1.0); + alt { + [] mDNS.receive(tr_MSLookup_mDNS_result_IPv4(id, domain, '42424242'O, 5060)) { + setverdict(pass); + } + [] mDNS.receive(MSLookup_mDNS:?) -> value vl_rmsg { + repeat; + } + [] T.timeout { + setverdict(fail, "OsmoHLR did not answer to mDNS query"); + } + } + + f_vty_subscr_delete(VTY, g_pars.sub); +} +testcase TC_MSLookup_mDNS_service_other_home() runs on test_CT { + var hexstring imsi := f_rnd_imsi('26242'H); + var HLR_ConnHdlr vc_conn; + var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi)); + + f_init(false); + f_vty_config(VTY, "mslookup", "mdns bind"); + f_vty_config2(VTY, {"mslookup", "server"}, "service sip.voice at 66.66.66.66 5060"); + + vc_conn := f_start_handler(refers(f_TC_MSLookup_mDNS_service_other_home), pars); + vc_conn.done; +} + /* TODO: * UL with ISD error * UL with ISD timeout @@ -1556,6 +1636,10 @@ control { execute( TC_subscr_create_on_demand_check_imei_early() ); execute( TC_subscr_create_on_demand_ul() ); execute( TC_subscr_create_on_demand_sai() ); + + if (mp_hlr_supports_dgsm) { + execute( TC_MSLookup_mDNS_service_other_home() ); + } }; }; diff --git a/hlr/gen_links.sh b/hlr/gen_links.sh index 872820dc9..14a3f8df2 100755 --- a/hlr/gen_links.sh +++ b/hlr/gen_links.sh @@ -35,11 +35,20 @@ FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types FILES+="SS_DataTypes.asn SS_Errors.asn SS_Operations.asn SS_PDU_Defs.asn SS_Protocol.asn SS_Types.ttcn SS_EncDec.cc" gen_links $DIR $FILES +DIR=$BASEDIR/titan.ProtocolModules.DNS/src +FILES="DNS_EncDec.cc DNS_Types.ttcn" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.TestPorts.UDPasp/src +FILES="UDPasp_PT.cc UDPasp_PT.hh UDPasp_PortType.ttcn UDPasp_Types.ttcn" +gen_links $DIR $FILES + DIR=../library FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp GSUP_Types.ttcn GSUP_Emulation.ttcn " FILES+="Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn " FILES+="Osmocom_VTY_Functions.ttcn " FILES+="SS_Templates.ttcn USSD_Helpers.ttcn " +FILES+="MSLookup_mDNS_Types.ttcn MSLookup_mDNS_Emulation.ttcn MSLookup_mDNS_Templates.ttcn" gen_links $DIR $FILES diff --git a/hlr/regen_makefile.sh b/hlr/regen_makefile.sh index 1a1d8123c..14b05daae 100755 --- a/hlr/regen_makefile.sh +++ b/hlr/regen_makefile.sh @@ -2,7 +2,7 @@ MAIN="HLR_Tests.ttcn" -FILES="*.ttcn *.ttcnpp IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc TELNETasp_PT.cc TCCEncoding.cc SS_EncDec.cc MAP_EncDec.cc *.asn" +FILES="*.ttcn *.ttcnpp DNS_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc TELNETasp_PT.cc TCCEncoding.cc UDPasp_PT.cc SS_EncDec.cc MAP_EncDec.cc *.asn" export CPPFLAGS_TTCN3="-DIPA_EMULATION_GSUP -DIPA_EMULATION_CTRL" diff --git a/library/MSLookup_mDNS_Emulation.ttcn b/library/MSLookup_mDNS_Emulation.ttcn new file mode 100644 index 000000000..029091deb --- /dev/null +++ b/library/MSLookup_mDNS_Emulation.ttcn @@ -0,0 +1,45 @@ +module MSLookup_mDNS_Emulation { + +/* (C) 2020 sysmocom s.f.m.c. GmbH + * All rights reserved. + * + * Released under the terms of GNU General Public License, Version 2 or + * (at your option) any later version. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +import from DNS_Types all; +import from UDPasp_Types all; +import from MSLookup_mDNS_Types all; + +/* Transcode between mDNS and UDP: + Wait for DNS packets on the mDNS port, encode them as UDP and forward them to the mDNS_UDP port. + Wait for UDP packets on mDNS_UDP port, decode them as DNS and forward them to the mDNS port. */ +function f_main() runs on MSLookup_mDNS_Emulation_CT +{ + var MSLookup_mDNS vl_dnsmsg; + var ASP_UDP vl_udpmsg; + map(self:mDNS_UDP, system:UDP); + alt { + [] mDNS_UDP.receive(ASP_UDP:?) -> value vl_udpmsg { + mDNS.send(MSLookup_mDNS: { + dec_PDU_DNS(vl_udpmsg.data), + vl_udpmsg.addressf, + vl_udpmsg.portf + }); + repeat; + } + [] mDNS.receive(MSLookup_mDNS:?) -> value vl_dnsmsg { + mDNS_UDP.send(ASP_UDP: { + enc_PDU_DNS(vl_dnsmsg.dnsMessage, false, true), + vl_dnsmsg.udpAddress, + vl_dnsmsg.udpPort + }); + repeat; + } + } + unmap(self:mDNS_UDP, system:UDP); +} + +} diff --git a/library/MSLookup_mDNS_Templates.ttcn b/library/MSLookup_mDNS_Templates.ttcn new file mode 100644 index 000000000..123ec1662 --- /dev/null +++ b/library/MSLookup_mDNS_Templates.ttcn @@ -0,0 +1,99 @@ + +/* (C) 2020 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Released under the terms of GNU General Public License, Version 2 or + * (at your option) any later version. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +module MSLookup_mDNS_Templates { + +import from DNS_Types all; +import from MSLookup_mDNS_Types all; + +template MSLookup_mDNS ts_MSLookup_mDNS_query(integer id, charstring domain) := { + dnsMessage := { + header := { + id := id, + qr := DNS_QUERY, + opCode := 0, + aa := false, + tc := false, + rd := false, + ra := false, + z := '000'B, + rCode := DNS_NO_ERROR, + qdCount := 1, + anCount := 0, + nsCount := 0, + arCount := 0 + }, + queries := { + { + qName := domain, + qType := 255, + qClass := DNS_IN + } + }, + answers := {}, + nameServerRecords := {}, + additionalRecords := {} + }, + udpAddress := "239.192.23.42", + udpPort := 4266 +} + +template MSLookup_mDNS tr_MSLookup_mDNS_result_IPv4(integer id, charstring domain, UInt32 ip_v4, integer port_v4) := { + dnsMessage := { + header := { + id := id, + qr := DNS_RESPONSE, + opCode := DNS_OP_QUERY, + aa := false, + tc := false, + rd := false, + ra := false, + z := '000'B, + rCode := DNS_NO_ERROR, + qdCount := 0, + anCount := 3, + nsCount := 0, + arCount := 0 + }, + queries := {}, + answers := { + { + name := domain, + rrType := DNS_TXT, + rrClass := DNS_IN, + ttl := ?, + rdLength := ?, + rData := {txt := {pattern "age=*"}} + }, + { + name := domain, + rrType := DNS_A, + rrClass := DNS_IN, + ttl := ?, + rdLength := ?, + rData := {a := ip_v4} + }, + { + name := domain, + rrType := DNS_TXT, + rrClass := DNS_IN, + ttl := ?, + rdLength := ?, + rData := {txt := {"port=" & int2str(port_v4)}} + } + }, + nameServerRecords := {}, + additionalRecords := {} + }, + udpAddress := ?, + udpPort := ? +} + +} diff --git a/library/MSLookup_mDNS_Types.ttcn b/library/MSLookup_mDNS_Types.ttcn new file mode 100644 index 000000000..dacbb2bc5 --- /dev/null +++ b/library/MSLookup_mDNS_Types.ttcn @@ -0,0 +1,31 @@ +module MSLookup_mDNS_Types { + +/* (C) 2020 sysmocom s.f.m.c. GmbH + * All rights reserved. + * + * Released under the terms of GNU General Public License, Version 2 or + * (at your option) any later version. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +import from DNS_Types all; +import from UDPasp_Types all; +import from UDPasp_PortType all; + +type record MSLookup_mDNS { + PDU_DNS dnsMessage, + AddressType udpAddress, + PortType udpPort +} + +type port MSLookup_mDNS_PT message { + inout MSLookup_mDNS +} with { extension "internal" } + +type component MSLookup_mDNS_Emulation_CT { + port MSLookup_mDNS_PT mDNS; + port UDPasp_PT mDNS_UDP; +} + +}