From e57af8a8e9afec0ee429d804e0ed190e9c80d840 Mon Sep 17 00:00:00 2001 From: paulmataruso Date: Thu, 21 Aug 2025 01:07:07 +0000 Subject: [PATCH] first commit --- 4g-external-ims-deploy.yaml | 384 +++++ 4g-volte-deploy.yaml | 486 +++++++ 4g-volte-ocs-deploy.yaml | 512 +++++++ 4g-volte-opensips-ims-deploy.yaml | 483 +++++++ LICENSE | 25 + README.md | 513 +++++++ amf/amf.yaml | 59 + amf/amf_init.sh | 39 + ausf/ausf.yaml | 24 + ausf/ausf_init.sh | 36 + base/Dockerfile | 133 ++ base/open5gs_init.sh | 102 ++ bsf/bsf.yaml | 26 + bsf/bsf_init.sh | 39 + custom_deployments/open5gs_hss_cx/.custom_env | 149 ++ .../4g-external-ims-deploy.yaml | 336 +++++ .../open5gs_hss_cx/4g-volte-deploy.yaml | 464 ++++++ .../4g-volte-opensips-ims-deploy.yaml | 462 ++++++ custom_deployments/open5gs_hss_cx/README.md | 37 + .../open5gs_hss_cx/dns/Dockerfile | 37 + .../open5gs_hss_cx/dns/dns_init.sh | 63 + .../open5gs_hss_cx/dns/e164.arpa | 14 + .../open5gs_hss_cx/dns/epc_zone | 15 + .../open5gs_hss_cx/dns/ims_zone | 27 + .../open5gs_hss_cx/dns/named.conf | 53 + .../open5gs_hss_cx/dns/pub_3gpp_zone | 13 + .../open5gs_hss_cx/hss/hss.conf | 267 ++++ .../open5gs_hss_cx/hss/hss.yaml | 13 + .../open5gs_hss_cx/hss/hss_init.sh | 62 + .../open5gs_hss_cx/hss/make_certs.sh | 29 + .../open5gs_hss_cx/icscf/icscf.cfg | 57 + .../open5gs_hss_cx/icscf/icscf.xml | 34 + .../open5gs_hss_cx/icscf/icscf_init.sh | 100 ++ .../open5gs_hss_cx/icscf/kamailio_icscf.cfg | 643 +++++++++ .../open5gs_hss_cx/mme/make_certs.sh | 30 + .../open5gs_hss_cx/mme/mme.conf | 266 ++++ .../open5gs_hss_cx/mme/mme.yaml | 59 + .../open5gs_hss_cx/mme/mme_init.sh | 58 + .../opensips_ims_icscf/freeDiameter.conf | 14 + .../opensips_ims_icscf/icscf.dictionary | 32 + .../opensips_ims_icscf/icscf_init.sh | 54 + .../opensips_ims_icscf/opensips.cfg | 226 +++ .../opensips_ims_scscf/freeDiameter.conf | 14 + .../opensips_ims_scscf/opensips.cfg | 311 ++++ .../opensips_ims_scscf/scscf.dictionary | 105 ++ .../opensips_ims_scscf/scscf_init.sh | 79 + .../open5gs_hss_cx/scscf/CxDataType_Rel6.xsd | 293 ++++ .../open5gs_hss_cx/scscf/CxDataType_Rel7.xsd | 301 ++++ .../open5gs_hss_cx/scscf/CxDataType_Rel8.xsd | 379 +++++ .../open5gs_hss_cx/scscf/dispatcher.list | 1 + .../open5gs_hss_cx/scscf/kamailio_scscf.cfg | 1281 +++++++++++++++++ .../open5gs_hss_cx/scscf/scscf.cfg | 89 ++ .../open5gs_hss_cx/scscf/scscf.xml | 36 + .../open5gs_hss_cx/scscf/scscf_init.sh | 87 ++ custom_deployments/open5gs_hss_cx/srsenb.yaml | 30 + custom_deployments/slicing/.custom_env | 169 +++ custom_deployments/slicing/README.md | 45 + custom_deployments/slicing/amf/amf.yaml | 62 + custom_deployments/slicing/amf/amf_init.sh | 39 + custom_deployments/slicing/nr-gnb.yaml | 29 + custom_deployments/slicing/nr-ue.yaml | 27 + custom_deployments/slicing/nr-ue2.yaml | 27 + custom_deployments/slicing/nssf/nssf.yaml | 34 + custom_deployments/slicing/nssf/nssf_init.sh | 37 + custom_deployments/slicing/sa-deploy.yaml | 401 ++++++ custom_deployments/slicing/smf/ip_utils.py | 70 + custom_deployments/slicing/smf/smf.yaml | 64 + custom_deployments/slicing/smf/smf2.yaml | 64 + custom_deployments/slicing/smf/smf2_init.sh | 57 + custom_deployments/slicing/smf/smf_init.sh | 60 + .../slicing/ueransim/ueransim-gnb.yaml | 25 + .../slicing/ueransim/ueransim-gnb_init.sh | 40 + .../slicing/ueransim/ueransim-ue.yaml | 72 + .../slicing/ueransim/ueransim-ue2.yaml | 72 + .../slicing/ueransim/ueransim-ue2_init.sh | 44 + .../slicing/ueransim/ueransim-ue_init.sh | 44 + custom_deployments/slicing/upf/ip_utils.py | 70 + custom_deployments/slicing/upf/tun_if.py | 111 ++ custom_deployments/slicing/upf/upf.yaml | 33 + custom_deployments/slicing/upf/upf2.yaml | 33 + custom_deployments/slicing/upf/upf2_init.sh | 72 + custom_deployments/slicing/upf/upf_init.sh | 73 + custom_deployments/with_eupf/.custom_env | 152 ++ custom_deployments/with_eupf/README.md | 27 + custom_deployments/with_eupf/nr-gnb.yaml | 29 + custom_deployments/with_eupf/nr-ue.yaml | 27 + custom_deployments/with_eupf/oaignb.yaml | 34 + custom_deployments/with_eupf/sa-deploy.yaml | 362 +++++ .../with_eupf/sa-vonr-deploy.yaml | 549 +++++++ custom_deployments/with_eupf/srsgnb.yaml | 30 + custom_deployments/with_eupf/srsgnb_zmq.yaml | 28 + .../with_eupf/srsue_5g_zmq.yaml | 28 + deploy-all.yaml | 712 +++++++++ dns/Dockerfile | 37 + dns/dns_init.sh | 64 + dns/e164.arpa | 17 + dns/epc_zone | 13 + dns/ims_zone | 37 + dns/named.conf | 53 + dns/pub_3gpp_zone | 13 + eupf/Dockerfile | 55 + eupf/eupf_init.sh | 46 + grafana/dashboards/open5gs_dashboard.json | 452 ++++++ grafana/dashboards/open5gs_dashboard.yml | 8 + grafana/datasources/prometheus_open5gs.yml | 9 + hss/hss.conf | 264 ++++ hss/hss.yaml | 12 + hss/hss_init.sh | 54 + hss/make_certs.sh | 29 + ibcf/Dockerfile | 90 ++ ibcf/README.md | 8 + ibcf/config/acl.conf | 1 + ibcf/config/asterisk.conf | 13 + ibcf/config/cdr.conf | 7 + ibcf/config/cdr_custom.conf | 4 + ibcf/config/confbridge.conf | 1 + ibcf/config/extensions.conf | 171 +++ ibcf/config/indications.conf | 21 + ibcf/config/logger.conf | 9 + ibcf/config/modules.conf | 130 ++ ibcf/config/musiconhold.conf | 5 + ibcf/config/pjsip.conf | 144 ++ ibcf/config/pjsip_notify.conf | 57 + ibcf/config/queues.conf | 19 + ibcf/config/rtp.conf | 3 + ibcf/config/voicemail.conf | 17 + ibcf/menuselect.makedeps | 234 +++ ibcf/menuselect.makeopts | 122 ++ ibcf/start-asterisk.sh | 43 + icscf/icscf.cfg | 56 + icscf/icscf.xml | 34 + icscf/icscf_init.sh | 97 ++ icscf/kamailio_icscf.cfg | 643 +++++++++ ims_base/Dockerfile | 53 + ims_base/kamailio_init.sh | 57 + ims_base/modules.lst | 24 + metrics/Dockerfile | 38 + metrics/metrics_init.sh | 45 + metrics/prometheus.yml | 22 + mme/make_certs.sh | 30 + mme/mme.conf | 266 ++++ mme/mme.yaml | 60 + mme/mme_init.sh | 57 + mysql/Dockerfile | 40 + mysql/mysql_init.sh | 60 + nr-gnb.yaml | 29 + nr-ue.yaml | 27 + nrf/nrf.yaml | 23 + nrf/nrf_init.sh | 37 + nssf/nssf.yaml | 29 + nssf/nssf_init.sh | 37 + oai/enb.band7.tm1.50PRB.usrpb210.conf | 315 ++++ oai/enb_dockerfile | 54 + oai/gnb.sa.band41.fr1.52PRB.usrpb210.conf | 288 ++++ oai/gnb.sa.band78.fr1.106PRB.usrpb210.conf | 267 ++++ oai/gnb_dockerfile | 53 + oai/oai_init.sh | 56 + oaienb.yaml | 34 + oaignb.yaml | 34 + ocs/Dockerfile | 31 + ocs/ocs_init.sh | 57 + ocs/start | 48 + ocs/sys.config | 82 ++ opensips_ims_base/Dockerfile | 52 + opensips_ims_base/Makefile.conf | 126 ++ opensips_ims_base/opensips_init.sh | 42 + opensips_ims_icscf/freeDiameter.conf | 13 + opensips_ims_icscf/icscf.dictionary | 32 + opensips_ims_icscf/icscf_init.sh | 51 + opensips_ims_icscf/opensips.cfg | 227 +++ opensips_ims_pcscf/db/dispatcher | 2 + opensips_ims_pcscf/db/version | 2 + opensips_ims_pcscf/freeDiameter.conf | 13 + opensips_ims_pcscf/opensips.cfg | 484 +++++++ opensips_ims_pcscf/opensips_vonr.cfg | 494 +++++++ opensips_ims_pcscf/pcscf.dictionary | 78 + opensips_ims_pcscf/pcscf_init.sh | 94 ++ opensips_ims_scscf/freeDiameter.conf | 13 + opensips_ims_scscf/opensips.cfg | 311 ++++ opensips_ims_scscf/scscf.dictionary | 105 ++ opensips_ims_scscf/scscf_init.sh | 76 + osmohlr/Dockerfile | 42 + osmohlr/osmo-hlr.cfg | 21 + osmohlr/osmohlr_init.sh | 34 + osmomsc/Dockerfile | 43 + osmomsc/osmo-msc.cfg | 61 + osmomsc/osmomsc_init.sh | 40 + pcf/pcf.yaml | 30 + pcf/pcf_init.sh | 39 + pcrf/make_certs.sh | 30 + pcrf/pcrf.conf | 266 ++++ pcrf/pcrf.yaml | 12 + pcrf/pcrf_init.sh | 55 + pcscf/dispatcher.list | 1 + pcscf/kamailio_pcscf.cfg | 1204 ++++++++++++++++ pcscf/pcscf.cfg | 152 ++ pcscf/pcscf.xml | 26 + pcscf/pcscf_init.sh | 99 ++ pcscf/route/mo.cfg | 680 +++++++++ pcscf/route/mt.cfg | 568 ++++++++ pcscf/route/register.cfg | 488 +++++++ pcscf/route/rtp.cfg | 216 +++ pcscf/route/websocket.cfg | 62 + pcscf/route/xmlrpc.cfg | 27 + pcscf/sems/etc/methodmap.conf | 2 + pcscf/sems/etc/mo.sbcprofile.conf | 78 + pcscf/sems/etc/monitoring.conf | 20 + pcscf/sems/etc/mt.sbcprofile.conf | 80 + pcscf/sems/etc/nocache.sbcprofile.conf | 38 + pcscf/sems/etc/refuse.sbcprofile.conf | 1 + .../sems/etc/refuse_with_200.sbcprofile.conf | 1 + pcscf/sems/etc/register.sbcprofile.conf | 28 + pcscf/sems/etc/rurimap.conf | 1 + pcscf/sems/etc/sbc.conf | 62 + pcscf/sems/etc/stats.conf | 5 + pcscf/sems/etc/xmlrpc2di.conf | 42 + pcscf/sems/sems.conf | 538 +++++++ pcscf/tls.cfg | 15 + pyhss/Dockerfile | 64 + pyhss/config.yaml | 150 ++ pyhss/default_ifc.xml | 174 +++ pyhss/default_sh_user_data.xml | 29 + pyhss/pyhss_init.sh | 76 + rtpengine/Dockerfile | 47 + rtpengine/rtpengine_init.sh | 92 ++ sa-deploy.yaml | 341 +++++ sa-vonr-deploy.yaml | 528 +++++++ sa-vonr-ibcf-deploy.yaml | 550 +++++++ sa-vonr-opensips-ims-deploy.yaml | 528 +++++++ scp/scp.yaml | 22 + scp/scp_init.sh | 35 + scscf/CxDataType_Rel6.xsd | 293 ++++ scscf/CxDataType_Rel7.xsd | 301 ++++ scscf/CxDataType_Rel8.xsd | 379 +++++ scscf/dispatcher.list | 1 + scscf/kamailio_scscf.cfg | 1279 ++++++++++++++++ scscf/scscf.cfg | 88 ++ scscf/scscf.xml | 36 + scscf/scscf_init.sh | 84 ++ sgwc/sgwc.yaml | 18 + sgwc/sgwc_init.sh | 37 + sgwu/sgwu.yaml | 20 + sgwu/sgwu_init.sh | 38 + sim/clone-vodafone-5g.script | 73 + sim/deactivate-5g.script | 70 + sim/iphone-private-5g.script | 76 + sim/readall-5g.script | 48 + smf/ip_utils.py | 70 + smf/make_certs.sh | 45 + smf/smf.conf | 266 ++++ smf/smf.yaml | 64 + smf/smf_4g.yaml | 58 + smf/smf_init.sh | 72 + smsc/kamailio_smsc.cfg | 443 ++++++ smsc/smsc-create.sql | 10 + smsc/smsc.cfg | 17 + smsc/smsc_init.sh | 70 + srsenb.yaml | 30 + srsenb_zmq.yaml | 28 + srsgnb.yaml | 30 + srsgnb_zmq.yaml | 28 + srslte/Dockerfile | 98 ++ srslte/enb.conf | 435 ++++++ srslte/enb_zmq.conf | 426 ++++++ srslte/gnb.conf | 435 ++++++ srslte/gnb_zmq.conf | 426 ++++++ srslte/rb_enb.conf | 310 ++++ srslte/rb_enb_zmq.conf | 310 ++++ srslte/rb_gnb.conf | 310 ++++ srslte/rb_gnb_zmq.conf | 310 ++++ srslte/rr_enb.conf | 118 ++ srslte/rr_enb_zmq.conf | 118 ++ srslte/rr_gnb.conf | 70 + srslte/rr_gnb_zmq.conf | 70 + srslte/sib_enb.conf | 294 ++++ srslte/sib_enb_zmq.conf | 294 ++++ srslte/sib_gnb.conf | 294 ++++ srslte/sib_gnb_zmq.conf | 294 ++++ srslte/srslte_init.sh | 96 ++ srslte/ue_5g_zmq.conf | 483 +++++++ srslte/ue_zmq.conf | 467 ++++++ srsran/Dockerfile | 50 + srsran/gnb.yml | 49 + srsran/gnb_zmq.yml | 59 + srsran/qos.yml | 707 +++++++++ srsran/srsran_init.sh | 59 + srsue_5g_zmq.yaml | 28 + srsue_zmq.yaml | 28 + udm/curve25519-1.key | 3 + udm/secp256r1-2.key | 8 + udm/udm.yaml | 31 + udm/udm_init.sh | 39 + udr/udr.yaml | 26 + udr/udr_init.sh | 39 + ueransim/Dockerfile | 78 + ueransim/ueransim-gnb.yaml | 22 + ueransim/ueransim-gnb_init.sh | 40 + ueransim/ueransim-ue.yaml | 69 + ueransim/ueransim-ue_init.sh | 44 + ueransim/ueransim_image_init.sh | 43 + upf/ip_utils.py | 70 + upf/tun_if.py | 111 ++ upf/upf.yaml | 40 + upf/upf_init.sh | 77 + webui/webui_init.sh | 34 + 305 files changed, 40120 insertions(+) create mode 100644 4g-external-ims-deploy.yaml create mode 100644 4g-volte-deploy.yaml create mode 100644 4g-volte-ocs-deploy.yaml create mode 100644 4g-volte-opensips-ims-deploy.yaml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 amf/amf.yaml create mode 100755 amf/amf_init.sh create mode 100644 ausf/ausf.yaml create mode 100755 ausf/ausf_init.sh create mode 100644 base/Dockerfile create mode 100755 base/open5gs_init.sh create mode 100644 bsf/bsf.yaml create mode 100755 bsf/bsf_init.sh create mode 100644 custom_deployments/open5gs_hss_cx/.custom_env create mode 100644 custom_deployments/open5gs_hss_cx/4g-external-ims-deploy.yaml create mode 100644 custom_deployments/open5gs_hss_cx/4g-volte-deploy.yaml create mode 100644 custom_deployments/open5gs_hss_cx/4g-volte-opensips-ims-deploy.yaml create mode 100644 custom_deployments/open5gs_hss_cx/README.md create mode 100644 custom_deployments/open5gs_hss_cx/dns/Dockerfile create mode 100755 custom_deployments/open5gs_hss_cx/dns/dns_init.sh create mode 100644 custom_deployments/open5gs_hss_cx/dns/e164.arpa create mode 100644 custom_deployments/open5gs_hss_cx/dns/epc_zone create mode 100644 custom_deployments/open5gs_hss_cx/dns/ims_zone create mode 100644 custom_deployments/open5gs_hss_cx/dns/named.conf create mode 100644 custom_deployments/open5gs_hss_cx/dns/pub_3gpp_zone create mode 100644 custom_deployments/open5gs_hss_cx/hss/hss.conf create mode 100644 custom_deployments/open5gs_hss_cx/hss/hss.yaml create mode 100755 custom_deployments/open5gs_hss_cx/hss/hss_init.sh create mode 100755 custom_deployments/open5gs_hss_cx/hss/make_certs.sh create mode 100644 custom_deployments/open5gs_hss_cx/icscf/icscf.cfg create mode 100644 custom_deployments/open5gs_hss_cx/icscf/icscf.xml create mode 100755 custom_deployments/open5gs_hss_cx/icscf/icscf_init.sh create mode 100644 custom_deployments/open5gs_hss_cx/icscf/kamailio_icscf.cfg create mode 100755 custom_deployments/open5gs_hss_cx/mme/make_certs.sh create mode 100644 custom_deployments/open5gs_hss_cx/mme/mme.conf create mode 100644 custom_deployments/open5gs_hss_cx/mme/mme.yaml create mode 100755 custom_deployments/open5gs_hss_cx/mme/mme_init.sh create mode 100644 custom_deployments/open5gs_hss_cx/opensips_ims_icscf/freeDiameter.conf create mode 100644 custom_deployments/open5gs_hss_cx/opensips_ims_icscf/icscf.dictionary create mode 100755 custom_deployments/open5gs_hss_cx/opensips_ims_icscf/icscf_init.sh create mode 100644 custom_deployments/open5gs_hss_cx/opensips_ims_icscf/opensips.cfg create mode 100644 custom_deployments/open5gs_hss_cx/opensips_ims_scscf/freeDiameter.conf create mode 100644 custom_deployments/open5gs_hss_cx/opensips_ims_scscf/opensips.cfg create mode 100644 custom_deployments/open5gs_hss_cx/opensips_ims_scscf/scscf.dictionary create mode 100755 custom_deployments/open5gs_hss_cx/opensips_ims_scscf/scscf_init.sh create mode 100644 custom_deployments/open5gs_hss_cx/scscf/CxDataType_Rel6.xsd create mode 100644 custom_deployments/open5gs_hss_cx/scscf/CxDataType_Rel7.xsd create mode 100644 custom_deployments/open5gs_hss_cx/scscf/CxDataType_Rel8.xsd create mode 100644 custom_deployments/open5gs_hss_cx/scscf/dispatcher.list create mode 100644 custom_deployments/open5gs_hss_cx/scscf/kamailio_scscf.cfg create mode 100644 custom_deployments/open5gs_hss_cx/scscf/scscf.cfg create mode 100644 custom_deployments/open5gs_hss_cx/scscf/scscf.xml create mode 100755 custom_deployments/open5gs_hss_cx/scscf/scscf_init.sh create mode 100644 custom_deployments/open5gs_hss_cx/srsenb.yaml create mode 100644 custom_deployments/slicing/.custom_env create mode 100644 custom_deployments/slicing/README.md create mode 100644 custom_deployments/slicing/amf/amf.yaml create mode 100755 custom_deployments/slicing/amf/amf_init.sh create mode 100644 custom_deployments/slicing/nr-gnb.yaml create mode 100644 custom_deployments/slicing/nr-ue.yaml create mode 100644 custom_deployments/slicing/nr-ue2.yaml create mode 100644 custom_deployments/slicing/nssf/nssf.yaml create mode 100755 custom_deployments/slicing/nssf/nssf_init.sh create mode 100644 custom_deployments/slicing/sa-deploy.yaml create mode 100755 custom_deployments/slicing/smf/ip_utils.py create mode 100644 custom_deployments/slicing/smf/smf.yaml create mode 100644 custom_deployments/slicing/smf/smf2.yaml create mode 100755 custom_deployments/slicing/smf/smf2_init.sh create mode 100755 custom_deployments/slicing/smf/smf_init.sh create mode 100644 custom_deployments/slicing/ueransim/ueransim-gnb.yaml create mode 100755 custom_deployments/slicing/ueransim/ueransim-gnb_init.sh create mode 100644 custom_deployments/slicing/ueransim/ueransim-ue.yaml create mode 100644 custom_deployments/slicing/ueransim/ueransim-ue2.yaml create mode 100755 custom_deployments/slicing/ueransim/ueransim-ue2_init.sh create mode 100755 custom_deployments/slicing/ueransim/ueransim-ue_init.sh create mode 100755 custom_deployments/slicing/upf/ip_utils.py create mode 100755 custom_deployments/slicing/upf/tun_if.py create mode 100644 custom_deployments/slicing/upf/upf.yaml create mode 100644 custom_deployments/slicing/upf/upf2.yaml create mode 100755 custom_deployments/slicing/upf/upf2_init.sh create mode 100755 custom_deployments/slicing/upf/upf_init.sh create mode 100644 custom_deployments/with_eupf/.custom_env create mode 100644 custom_deployments/with_eupf/README.md create mode 100644 custom_deployments/with_eupf/nr-gnb.yaml create mode 100644 custom_deployments/with_eupf/nr-ue.yaml create mode 100644 custom_deployments/with_eupf/oaignb.yaml create mode 100644 custom_deployments/with_eupf/sa-deploy.yaml create mode 100644 custom_deployments/with_eupf/sa-vonr-deploy.yaml create mode 100644 custom_deployments/with_eupf/srsgnb.yaml create mode 100644 custom_deployments/with_eupf/srsgnb_zmq.yaml create mode 100644 custom_deployments/with_eupf/srsue_5g_zmq.yaml create mode 100644 deploy-all.yaml create mode 100644 dns/Dockerfile create mode 100755 dns/dns_init.sh create mode 100644 dns/e164.arpa create mode 100644 dns/epc_zone create mode 100644 dns/ims_zone create mode 100644 dns/named.conf create mode 100644 dns/pub_3gpp_zone create mode 100644 eupf/Dockerfile create mode 100755 eupf/eupf_init.sh create mode 100644 grafana/dashboards/open5gs_dashboard.json create mode 100644 grafana/dashboards/open5gs_dashboard.yml create mode 100644 grafana/datasources/prometheus_open5gs.yml create mode 100644 hss/hss.conf create mode 100644 hss/hss.yaml create mode 100755 hss/hss_init.sh create mode 100755 hss/make_certs.sh create mode 100644 ibcf/Dockerfile create mode 100644 ibcf/README.md create mode 100644 ibcf/config/acl.conf create mode 100644 ibcf/config/asterisk.conf create mode 100644 ibcf/config/cdr.conf create mode 100644 ibcf/config/cdr_custom.conf create mode 100644 ibcf/config/confbridge.conf create mode 100644 ibcf/config/extensions.conf create mode 100644 ibcf/config/indications.conf create mode 100644 ibcf/config/logger.conf create mode 100644 ibcf/config/modules.conf create mode 100644 ibcf/config/musiconhold.conf create mode 100644 ibcf/config/pjsip.conf create mode 100644 ibcf/config/pjsip_notify.conf create mode 100644 ibcf/config/queues.conf create mode 100644 ibcf/config/rtp.conf create mode 100644 ibcf/config/voicemail.conf create mode 100644 ibcf/menuselect.makedeps create mode 100644 ibcf/menuselect.makeopts create mode 100755 ibcf/start-asterisk.sh create mode 100644 icscf/icscf.cfg create mode 100644 icscf/icscf.xml create mode 100755 icscf/icscf_init.sh create mode 100644 icscf/kamailio_icscf.cfg create mode 100644 ims_base/Dockerfile create mode 100755 ims_base/kamailio_init.sh create mode 100644 ims_base/modules.lst create mode 100644 metrics/Dockerfile create mode 100755 metrics/metrics_init.sh create mode 100644 metrics/prometheus.yml create mode 100755 mme/make_certs.sh create mode 100644 mme/mme.conf create mode 100644 mme/mme.yaml create mode 100755 mme/mme_init.sh create mode 100644 mysql/Dockerfile create mode 100755 mysql/mysql_init.sh create mode 100644 nr-gnb.yaml create mode 100644 nr-ue.yaml create mode 100644 nrf/nrf.yaml create mode 100755 nrf/nrf_init.sh create mode 100644 nssf/nssf.yaml create mode 100755 nssf/nssf_init.sh create mode 100644 oai/enb.band7.tm1.50PRB.usrpb210.conf create mode 100644 oai/enb_dockerfile create mode 100644 oai/gnb.sa.band41.fr1.52PRB.usrpb210.conf create mode 100644 oai/gnb.sa.band78.fr1.106PRB.usrpb210.conf create mode 100644 oai/gnb_dockerfile create mode 100755 oai/oai_init.sh create mode 100644 oaienb.yaml create mode 100644 oaignb.yaml create mode 100644 ocs/Dockerfile create mode 100755 ocs/ocs_init.sh create mode 100755 ocs/start create mode 100644 ocs/sys.config create mode 100644 opensips_ims_base/Dockerfile create mode 100644 opensips_ims_base/Makefile.conf create mode 100755 opensips_ims_base/opensips_init.sh create mode 100644 opensips_ims_icscf/freeDiameter.conf create mode 100644 opensips_ims_icscf/icscf.dictionary create mode 100755 opensips_ims_icscf/icscf_init.sh create mode 100644 opensips_ims_icscf/opensips.cfg create mode 100644 opensips_ims_pcscf/db/dispatcher create mode 100644 opensips_ims_pcscf/db/version create mode 100644 opensips_ims_pcscf/freeDiameter.conf create mode 100644 opensips_ims_pcscf/opensips.cfg create mode 100644 opensips_ims_pcscf/opensips_vonr.cfg create mode 100644 opensips_ims_pcscf/pcscf.dictionary create mode 100755 opensips_ims_pcscf/pcscf_init.sh create mode 100644 opensips_ims_scscf/freeDiameter.conf create mode 100644 opensips_ims_scscf/opensips.cfg create mode 100644 opensips_ims_scscf/scscf.dictionary create mode 100755 opensips_ims_scscf/scscf_init.sh create mode 100644 osmohlr/Dockerfile create mode 100644 osmohlr/osmo-hlr.cfg create mode 100755 osmohlr/osmohlr_init.sh create mode 100644 osmomsc/Dockerfile create mode 100644 osmomsc/osmo-msc.cfg create mode 100755 osmomsc/osmomsc_init.sh create mode 100644 pcf/pcf.yaml create mode 100755 pcf/pcf_init.sh create mode 100755 pcrf/make_certs.sh create mode 100644 pcrf/pcrf.conf create mode 100644 pcrf/pcrf.yaml create mode 100755 pcrf/pcrf_init.sh create mode 100644 pcscf/dispatcher.list create mode 100644 pcscf/kamailio_pcscf.cfg create mode 100644 pcscf/pcscf.cfg create mode 100644 pcscf/pcscf.xml create mode 100755 pcscf/pcscf_init.sh create mode 100644 pcscf/route/mo.cfg create mode 100644 pcscf/route/mt.cfg create mode 100644 pcscf/route/register.cfg create mode 100644 pcscf/route/rtp.cfg create mode 100644 pcscf/route/websocket.cfg create mode 100644 pcscf/route/xmlrpc.cfg create mode 100644 pcscf/sems/etc/methodmap.conf create mode 100644 pcscf/sems/etc/mo.sbcprofile.conf create mode 100644 pcscf/sems/etc/monitoring.conf create mode 100644 pcscf/sems/etc/mt.sbcprofile.conf create mode 100644 pcscf/sems/etc/nocache.sbcprofile.conf create mode 100644 pcscf/sems/etc/refuse.sbcprofile.conf create mode 100644 pcscf/sems/etc/refuse_with_200.sbcprofile.conf create mode 100644 pcscf/sems/etc/register.sbcprofile.conf create mode 100644 pcscf/sems/etc/rurimap.conf create mode 100644 pcscf/sems/etc/sbc.conf create mode 100644 pcscf/sems/etc/stats.conf create mode 100644 pcscf/sems/etc/xmlrpc2di.conf create mode 100644 pcscf/sems/sems.conf create mode 100644 pcscf/tls.cfg create mode 100644 pyhss/Dockerfile create mode 100644 pyhss/config.yaml create mode 100644 pyhss/default_ifc.xml create mode 100644 pyhss/default_sh_user_data.xml create mode 100755 pyhss/pyhss_init.sh create mode 100644 rtpengine/Dockerfile create mode 100755 rtpengine/rtpengine_init.sh create mode 100644 sa-deploy.yaml create mode 100644 sa-vonr-deploy.yaml create mode 100644 sa-vonr-ibcf-deploy.yaml create mode 100644 sa-vonr-opensips-ims-deploy.yaml create mode 100644 scp/scp.yaml create mode 100755 scp/scp_init.sh create mode 100644 scscf/CxDataType_Rel6.xsd create mode 100644 scscf/CxDataType_Rel7.xsd create mode 100644 scscf/CxDataType_Rel8.xsd create mode 100644 scscf/dispatcher.list create mode 100644 scscf/kamailio_scscf.cfg create mode 100644 scscf/scscf.cfg create mode 100644 scscf/scscf.xml create mode 100755 scscf/scscf_init.sh create mode 100644 sgwc/sgwc.yaml create mode 100755 sgwc/sgwc_init.sh create mode 100644 sgwu/sgwu.yaml create mode 100755 sgwu/sgwu_init.sh create mode 100644 sim/clone-vodafone-5g.script create mode 100644 sim/deactivate-5g.script create mode 100644 sim/iphone-private-5g.script create mode 100644 sim/readall-5g.script create mode 100755 smf/ip_utils.py create mode 100755 smf/make_certs.sh create mode 100644 smf/smf.conf create mode 100644 smf/smf.yaml create mode 100644 smf/smf_4g.yaml create mode 100755 smf/smf_init.sh create mode 100644 smsc/kamailio_smsc.cfg create mode 100644 smsc/smsc-create.sql create mode 100644 smsc/smsc.cfg create mode 100755 smsc/smsc_init.sh create mode 100644 srsenb.yaml create mode 100644 srsenb_zmq.yaml create mode 100644 srsgnb.yaml create mode 100644 srsgnb_zmq.yaml create mode 100644 srslte/Dockerfile create mode 100644 srslte/enb.conf create mode 100644 srslte/enb_zmq.conf create mode 100644 srslte/gnb.conf create mode 100644 srslte/gnb_zmq.conf create mode 100644 srslte/rb_enb.conf create mode 100644 srslte/rb_enb_zmq.conf create mode 100644 srslte/rb_gnb.conf create mode 100644 srslte/rb_gnb_zmq.conf create mode 100644 srslte/rr_enb.conf create mode 100644 srslte/rr_enb_zmq.conf create mode 100644 srslte/rr_gnb.conf create mode 100644 srslte/rr_gnb_zmq.conf create mode 100644 srslte/sib_enb.conf create mode 100644 srslte/sib_enb_zmq.conf create mode 100644 srslte/sib_gnb.conf create mode 100644 srslte/sib_gnb_zmq.conf create mode 100755 srslte/srslte_init.sh create mode 100644 srslte/ue_5g_zmq.conf create mode 100644 srslte/ue_zmq.conf create mode 100644 srsran/Dockerfile create mode 100644 srsran/gnb.yml create mode 100644 srsran/gnb_zmq.yml create mode 100644 srsran/qos.yml create mode 100755 srsran/srsran_init.sh create mode 100644 srsue_5g_zmq.yaml create mode 100644 srsue_zmq.yaml create mode 100644 udm/curve25519-1.key create mode 100644 udm/secp256r1-2.key create mode 100644 udm/udm.yaml create mode 100755 udm/udm_init.sh create mode 100644 udr/udr.yaml create mode 100755 udr/udr_init.sh create mode 100644 ueransim/Dockerfile create mode 100644 ueransim/ueransim-gnb.yaml create mode 100755 ueransim/ueransim-gnb_init.sh create mode 100644 ueransim/ueransim-ue.yaml create mode 100755 ueransim/ueransim-ue_init.sh create mode 100755 ueransim/ueransim_image_init.sh create mode 100755 upf/ip_utils.py create mode 100755 upf/tun_if.py create mode 100644 upf/upf.yaml create mode 100755 upf/upf_init.sh create mode 100755 webui/webui_init.sh diff --git a/4g-external-ims-deploy.yaml b/4g-external-ims-deploy.yaml new file mode 100644 index 0000000..33d5d01 --- /dev/null +++ b/4g-external-ims-deploy.yaml @@ -0,0 +1,384 @@ +services: + mongo: + image: mongo:6.0 + container_name: mongo + command: --bind_ip 0.0.0.0 + env_file: + - .env + volumes: + - mongodbdata:/data/db + - mongodbdata:/data/configdb + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "27017/udp" + - "27017/tcp" + networks: + default: + ipv4_address: ${MONGO_IP} + webui: + image: docker_open5gs + container_name: webui + depends_on: + - mongo + env_file: + - .env + environment: + - COMPONENT_NAME=webui + volumes: + - ./webui:/mnt/webui + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9999/tcp" + ports: + - "9999:9999/tcp" + networks: + default: + ipv4_address: ${WEBUI_IP} + hss: + image: docker_open5gs + container_name: hss + env_file: + - .env + environment: + - COMPONENT_NAME=hss + volumes: + - ./hss:/mnt/hss + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + depends_on: + - mongo + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + networks: + default: + ipv4_address: ${HSS_IP} + sgwc: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwc + env_file: + - .env + environment: + - COMPONENT_NAME=sgwc + volumes: + - ./sgwc:/mnt/sgwc + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2123/udp" + - "8805/udp" + networks: + default: + ipv4_address: ${SGWC_IP} + sgwu: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwu + env_file: + - .env + environment: + - COMPONENT_NAME=sgwu + volumes: + - ./sgwu:/mnt/sgwu + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "8805/udp" + - "2152/udp" + # ports: + # - "${SGWU_ADVERTISE_IP}:2152:2152/udp" + networks: + default: + ipv4_address: ${SGWU_IP} + smf: + image: docker_open5gs + container_name: smf + env_file: + - .env + environment: + - COMPONENT_NAME=smf + - DEPLOY_MODE=4G + volumes: + - ./smf:/mnt/smf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "8805/udp" + - "2123/udp" + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${SMF_IP} + upf: + image: docker_open5gs + depends_on: + - smf + container_name: upf + env_file: + - .env + environment: + - COMPONENT_NAME=upf + volumes: + - ./upf:/mnt/upf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2152/udp" + - "8805/udp" + - "9091/tcp" + cap_add: + - NET_ADMIN + privileged: true + # sysctls: + # - net.ipv4.ip_forward=1 + # - net.ipv6.conf.all.disable_ipv6=0 + network_mode: host + mme: + image: docker_open5gs + depends_on: + - hss + - sgwc + - sgwu + - smf + - upf + - osmomsc + container_name: mme + env_file: + - .env + environment: + - COMPONENT_NAME=mme + volumes: + - ./mme:/mnt/mme + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "36412/sctp" + - "2123/udp" + - "9091/tcp" + # ports: + # - "36412:36412/sctp" + networks: + default: + ipv4_address: ${MME_IP} + pcrf: + image: docker_open5gs + container_name: pcrf + env_file: + - .env + environment: + - COMPONENT_NAME=pcrf + depends_on: + - mongo + volumes: + - ./pcrf:/mnt/pcrf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "${PCRF_BIND_PORT}/tcp" + - "${PCRF_BIND_PORT}/sctp" + - "5868/tcp" + - "5868/sctp" + # ports: + # - "${PCRF_BIND_PORT}:${PCRF_BIND_PORT}/sctp" + # - "${PCRF_BIND_PORT}:${PCRF_BIND_PORT}/tcp" + networks: + default: + ipv4_address: ${PCRF_IP} + ocs: + build: ./ocs + image: docker_ocs + container_name: ocs + env_file: + - .env + environment: + - COMPONENT_NAME=ocs + depends_on: + - smf + volumes: + - ./ocs:/mnt/ocs + - ocsdbdata:/home/otp/db + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "${OCS_BIND_PORT}/tcp" + - "${OCS_BIND_PORT}/sctp" + - "8083/tcp" + ports: + - "8083:8083/tcp" + networks: + default: + ipv4_address: ${OCS_IP} + dns: + build: ./dns + image: docker_dns + container_name: dns + env_file: + - .env + volumes: + - ./dns:/mnt/dns + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "53/udp" + networks: + default: + ipv4_address: ${DNS_IP} + mysql: + build: ./mysql + image: docker_mysql + container_name: mysql + env_file: + - .env + volumes: + - dbdata:/var/lib/mysql + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3306/tcp" + networks: + default: + ipv4_address: ${MYSQL_IP} + pyhss: + build: ./pyhss + image: docker_pyhss + container_name: pyhss + dns: ${DNS_IP} + volumes: + - ./pyhss:/mnt/pyhss + - ./pyhss/logs:/pyhss/log/ + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + depends_on: + - dns + - mysql + expose: + - "${PYHSS_BIND_PORT}/tcp" + - "${PYHSS_BIND_PORT}/sctp" + ports: + # - "${PYHSS_BIND_PORT}:${PYHSS_BIND_PORT}/sctp" + # - "${PYHSS_BIND_PORT}:${PYHSS_BIND_PORT}/tcp" + - "8080:8080/tcp" + networks: + default: + ipv4_address: ${PYHSS_IP} + osmomsc: + build: ./osmomsc + image: docker_osmomsc + container_name: osmomsc + volumes: + - ./osmomsc:/mnt/osmomsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=osmomsc + depends_on: + - osmohlr + expose: + - "29118/sctp" + - "2775/tcp" + networks: + default: + ipv4_address: ${OSMOMSC_IP} + osmohlr: + build: ./osmohlr + image: docker_osmohlr + container_name: osmohlr + volumes: + - ./osmohlr:/mnt/osmohlr + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=osmohlr + expose: + - "4222/tcp" + networks: + default: + ipv4_address: ${OSMOHLR_IP} + metrics: + build: ./metrics + image: docker_metrics + container_name: metrics + env_file: + - .env + volumes: + - ./metrics:/mnt/metrics + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9090/tcp" + ports: + - "9090:9090/tcp" + networks: + default: + ipv4_address: ${METRICS_IP} + grafana: + image: grafana/grafana:11.3.0 + container_name: grafana + env_file: + - .env + volumes: + - grafana_data:/var/lib/grafana + - ./grafana/:/etc/grafana/provisioning/ + - ./grafana:/mnt/grafana + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} + #- GF_INSTALL_PLUGINS=${GRAFANA_INSTALL_PLUGINS} + - GF_PATHS_PROVISIONING=/etc/grafana/provisioning + - GF_PATHS_DATA=/var/lib/grafana + - METRICS_IP=${METRICS_IP} + expose: + - "3000/tcp" + ports: + - "3000:3000/tcp" + networks: + default: + ipv4_address: ${GRAFANA_IP} +networks: + default: + name: docker_open5gs_default + ipam: + config: + - subnet: ${TEST_NETWORK} +volumes: + grafana_data: + name: grafana_data + mongodbdata: + name: docker_open5gs_mongodbdata + dbdata: + name: docker_open5gs_dbdata + ocsdbdata: + name: docker_open5gs_ocsdbdata diff --git a/4g-volte-deploy.yaml b/4g-volte-deploy.yaml new file mode 100644 index 0000000..a0b9665 --- /dev/null +++ b/4g-volte-deploy.yaml @@ -0,0 +1,486 @@ +services: + mongo: + image: mongo:6.0 + container_name: mongo + command: --bind_ip 0.0.0.0 + env_file: + - .env + volumes: + - mongodbdata:/data/db + - mongodbdata:/data/configdb + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "27017/udp" + - "27017/tcp" + networks: + default: + ipv4_address: ${MONGO_IP} + webui: + image: docker_open5gs + container_name: webui + depends_on: + - mongo + env_file: + - .env + environment: + - COMPONENT_NAME=webui + volumes: + - ./webui:/mnt/webui + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9999/tcp" + ports: + - "9999:9999/tcp" + networks: + default: + ipv4_address: ${WEBUI_IP} + hss: + image: docker_open5gs + container_name: hss + env_file: + - .env + environment: + - COMPONENT_NAME=hss + volumes: + - ./hss:/mnt/hss + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + depends_on: + - mongo + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + networks: + default: + ipv4_address: ${HSS_IP} + sgwc: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwc + env_file: + - .env + environment: + - COMPONENT_NAME=sgwc + volumes: + - ./sgwc:/mnt/sgwc + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2123/udp" + - "8805/udp" + networks: + default: + ipv4_address: ${SGWC_IP} + sgwu: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwu + env_file: + - .env + environment: + - COMPONENT_NAME=sgwu + volumes: + - ./sgwu:/mnt/sgwu + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "8805/udp" + - "2152/udp" + ports: + - "2152:2152/udp" + networks: + default: + ipv4_address: ${SGWU_IP} + smf: + image: docker_open5gs + container_name: smf + env_file: + - .env + environment: + - COMPONENT_NAME=smf + - DEPLOY_MODE=4G + volumes: + - ./smf:/mnt/smf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "8805/udp" + - "2123/udp" + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${SMF_IP} + upf: + image: docker_open5gs + depends_on: + - smf + container_name: upf + env_file: + - .env + environment: + - COMPONENT_NAME=upf + volumes: + - ./upf:/mnt/upf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2152/udp" + - "8805/udp" + - "9091/tcp" + cap_add: + - NET_ADMIN + privileged: true + sysctls: + - net.ipv4.ip_forward=1 + networks: + default: + ipv4_address: ${UPF_IP} + mme: + image: docker_open5gs + depends_on: + - hss + - sgwc + - sgwu + - smf + - upf + - osmomsc + container_name: mme + env_file: + - .env + environment: + - COMPONENT_NAME=mme + volumes: + - ./mme:/mnt/mme + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "36412/sctp" + - "2123/udp" + - "9091/tcp" + ports: + - "36412:36412/sctp" + networks: + default: + ipv4_address: ${MME_IP} + pcrf: + image: docker_open5gs + container_name: pcrf + env_file: + - .env + environment: + - COMPONENT_NAME=pcrf + depends_on: + - mongo + volumes: + - ./pcrf:/mnt/pcrf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "${PCRF_BIND_PORT}/tcp" + - "${PCRF_BIND_PORT}/sctp" + - "5868/tcp" + - "5868/sctp" + networks: + default: + ipv4_address: ${PCRF_IP} + dns: + build: ./dns + image: docker_dns + container_name: dns + env_file: + - .env + volumes: + - ./dns:/mnt/dns + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "53/udp" + networks: + default: + ipv4_address: ${DNS_IP} + rtpengine: + build: ./rtpengine + image: docker_rtpengine + container_name: rtpengine + privileged: true + env_file: + - .env + volumes: + - ./rtpengine:/mnt/rtpengine + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + cap_add: + - NET_ADMIN + environment: + - TABLE=0 + - INTERFACE=${RTPENGINE_IP} + - LISTEN_NG=${RTPENGINE_IP}:2223 + - PIDFILE=/run/ngcp-rtpengine-daemon.pid + - PORT_MAX=50000 + - PORT_MIN=49000 + - NO_FALLBACK=no + - TOS=184 + expose: + - "2223/udp" + - "49000-50000/udp" + networks: + default: + ipv4_address: ${RTPENGINE_IP} + mysql: + build: ./mysql + image: docker_mysql + container_name: mysql + env_file: + - .env + volumes: + - dbdata:/var/lib/mysql + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3306/tcp" + networks: + default: + ipv4_address: ${MYSQL_IP} + pyhss: + build: ./pyhss + image: docker_pyhss + container_name: pyhss + dns: ${DNS_IP} + volumes: + - ./pyhss:/mnt/pyhss + - ./pyhss/logs:/pyhss/log/ + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + depends_on: + - dns + - mysql + expose: + - "${PYHSS_BIND_PORT}/tcp" + - "${PYHSS_BIND_PORT}/sctp" + - "8080/tcp" + ports: + - "8080:8080/tcp" + networks: + default: + ipv4_address: ${PYHSS_IP} + icscf: + image: docker_kamailio + container_name: icscf + dns: ${DNS_IP} + volumes: + - ./icscf:/mnt/icscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=icscf + depends_on: + - dns + - mysql + - pyhss + expose: + - "${ICSCF_BIND_PORT}/tcp" + - "${ICSCF_BIND_PORT}/sctp" + - "4060/udp" + - "4060/tcp" + networks: + default: + ipv4_address: ${ICSCF_IP} + scscf: + image: docker_kamailio + container_name: scscf + dns: ${DNS_IP} + volumes: + - ./scscf:/mnt/scscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=scscf + depends_on: + - dns + - mysql + - pyhss + expose: + - "${SCSCF_BIND_PORT}/tcp" + - "${SCSCF_BIND_PORT}/sctp" + - "6060/udp" + - "6060/tcp" + networks: + default: + ipv4_address: ${SCSCF_IP} + pcscf: + image: docker_kamailio + container_name: pcscf + dns: ${DNS_IP} + privileged: true + cap_add: + - NET_ADMIN + volumes: + - ./pcscf:/mnt/pcscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=pcscf + - DEPLOY_MODE=4G + depends_on: + - dns + - mysql + - rtpengine + - icscf + - scscf + expose: + - "${PCSCF_BIND_PORT}/tcp" + - "${PCSCF_BIND_PORT}/sctp" + - "5060/tcp" + - "5060/udp" + - "5100-5120/tcp" + - "5100-5120/udp" + - "6100-6120/tcp" + - "6100-6120/udp" + networks: + default: + ipv4_address: ${PCSCF_IP} + smsc: + image: docker_kamailio + container_name: smsc + dns: ${DNS_IP} + volumes: + - ./smsc:/mnt/smsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=smsc + depends_on: + - dns + - mysql + expose: + - "7090/udp" + - "7090/tcp" + networks: + default: + ipv4_address: ${SMSC_IP} + osmomsc: + build: ./osmomsc + image: docker_osmomsc + container_name: osmomsc + volumes: + - ./osmomsc:/mnt/osmomsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=osmomsc + depends_on: + - osmohlr + expose: + - "29118/sctp" + - "2775/tcp" + networks: + default: + ipv4_address: ${OSMOMSC_IP} + osmohlr: + build: ./osmohlr + image: docker_osmohlr + container_name: osmohlr + volumes: + - ./osmohlr:/mnt/osmohlr + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=osmohlr + expose: + - "4222/tcp" + networks: + default: + ipv4_address: ${OSMOHLR_IP} + metrics: + build: ./metrics + image: docker_metrics + container_name: metrics + env_file: + - .env + volumes: + - ./metrics:/mnt/metrics + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9090/tcp" + ports: + - "9090:9090/tcp" + networks: + default: + ipv4_address: ${METRICS_IP} + grafana: + image: grafana/grafana:11.3.0 + container_name: grafana + env_file: + - .env + volumes: + - grafana_data:/var/lib/grafana + - ./grafana/:/etc/grafana/provisioning/ + - ./grafana:/mnt/grafana + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} + #- GF_INSTALL_PLUGINS=${GRAFANA_INSTALL_PLUGINS} + - GF_PATHS_PROVISIONING=/etc/grafana/provisioning + - GF_PATHS_DATA=/var/lib/grafana + - METRICS_IP=${METRICS_IP} + expose: + - "3000/tcp" + ports: + - "3000:3000/tcp" + networks: + default: + ipv4_address: ${GRAFANA_IP} +networks: + default: + name: docker_open5gs_default + ipam: + config: + - subnet: ${TEST_NETWORK} +volumes: + grafana_data: + name: grafana_data + mongodbdata: + name: docker_open5gs_mongodbdata + dbdata: + name: docker_open5gs_dbdata diff --git a/4g-volte-ocs-deploy.yaml b/4g-volte-ocs-deploy.yaml new file mode 100644 index 0000000..9f08498 --- /dev/null +++ b/4g-volte-ocs-deploy.yaml @@ -0,0 +1,512 @@ +services: + mongo: + image: mongo:6.0 + container_name: mongo + command: --bind_ip 0.0.0.0 + env_file: + - .env + volumes: + - mongodbdata:/data/db + - mongodbdata:/data/configdb + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "27017/udp" + - "27017/tcp" + networks: + default: + ipv4_address: ${MONGO_IP} + webui: + image: docker_open5gs + container_name: webui + depends_on: + - mongo + env_file: + - .env + environment: + - COMPONENT_NAME=webui + volumes: + - ./webui:/mnt/webui + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9999/tcp" + ports: + - "9999:9999/tcp" + networks: + default: + ipv4_address: ${WEBUI_IP} + hss: + image: docker_open5gs + container_name: hss + env_file: + - .env + environment: + - COMPONENT_NAME=hss + volumes: + - ./hss:/mnt/hss + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + depends_on: + - mongo + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + networks: + default: + ipv4_address: ${HSS_IP} + sgwc: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwc + env_file: + - .env + environment: + - COMPONENT_NAME=sgwc + volumes: + - ./sgwc:/mnt/sgwc + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2123/udp" + - "8805/udp" + networks: + default: + ipv4_address: ${SGWC_IP} + sgwu: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwu + env_file: + - .env + environment: + - COMPONENT_NAME=sgwu + volumes: + - ./sgwu:/mnt/sgwu + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "8805/udp" + - "2152/udp" + # ports: + # - "2152:2152/udp" + networks: + default: + ipv4_address: ${SGWU_IP} + smf: + image: docker_open5gs + container_name: smf + env_file: + - .env + environment: + - COMPONENT_NAME=smf + - DEPLOY_MODE=4G + volumes: + - ./smf:/mnt/smf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "8805/udp" + - "2123/udp" + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${SMF_IP} + upf: + image: docker_open5gs + depends_on: + - smf + container_name: upf + env_file: + - .env + environment: + - COMPONENT_NAME=upf + volumes: + - ./upf:/mnt/upf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2152/udp" + - "8805/udp" + - "9091/tcp" + cap_add: + - NET_ADMIN + privileged: true + sysctls: + - net.ipv4.ip_forward=1 + networks: + default: + ipv4_address: ${UPF_IP} + mme: + image: docker_open5gs + depends_on: + - hss + - sgwc + - sgwu + - smf + - upf + - osmomsc + container_name: mme + env_file: + - .env + environment: + - COMPONENT_NAME=mme + volumes: + - ./mme:/mnt/mme + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "36412/sctp" + - "2123/udp" + - "9091/tcp" + # ports: + # - "36412:36412/sctp" + networks: + default: + ipv4_address: ${MME_IP} + pcrf: + image: docker_open5gs + container_name: pcrf + env_file: + - .env + environment: + - COMPONENT_NAME=pcrf + depends_on: + - mongo + volumes: + - ./pcrf:/mnt/pcrf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "${PCRF_BIND_PORT}/tcp" + - "${PCRF_BIND_PORT}/sctp" + - "5868/tcp" + - "5868/sctp" + networks: + default: + ipv4_address: ${PCRF_IP} + ocs: + build: ./ocs + image: docker_ocs + container_name: ocs + env_file: + - .env + environment: + - COMPONENT_NAME=ocs + depends_on: + - smf + volumes: + - ./ocs:/mnt/ocs + - ocsdbdata:/home/otp/db + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "${OCS_BIND_PORT}/tcp" + - "${OCS_BIND_PORT}/sctp" + - "8083/tcp" + ports: + - "8083:8083/tcp" + networks: + default: + ipv4_address: ${OCS_IP} + dns: + build: ./dns + image: docker_dns + container_name: dns + env_file: + - .env + volumes: + - ./dns:/mnt/dns + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "53/udp" + networks: + default: + ipv4_address: ${DNS_IP} + rtpengine: + build: ./rtpengine + image: docker_rtpengine + container_name: rtpengine + privileged: true + env_file: + - .env + volumes: + - ./rtpengine:/mnt/rtpengine + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + cap_add: + - NET_ADMIN + environment: + - TABLE=0 + - INTERFACE=${RTPENGINE_IP} + - LISTEN_NG=${RTPENGINE_IP}:2223 + - PIDFILE=/run/ngcp-rtpengine-daemon.pid + - PORT_MAX=50000 + - PORT_MIN=49000 + - NO_FALLBACK=no + - TOS=184 + expose: + - "2223/udp" + - "49000-50000/udp" + networks: + default: + ipv4_address: ${RTPENGINE_IP} + mysql: + build: ./mysql + image: docker_mysql + container_name: mysql + env_file: + - .env + volumes: + - dbdata:/var/lib/mysql + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3306/tcp" + networks: + default: + ipv4_address: ${MYSQL_IP} + pyhss: + build: ./pyhss + image: docker_pyhss + container_name: pyhss + dns: ${DNS_IP} + volumes: + - ./pyhss:/mnt/pyhss + - ./pyhss/logs:/pyhss/log/ + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + depends_on: + - dns + - mysql + expose: + - "${PYHSS_BIND_PORT}/tcp" + - "${PYHSS_BIND_PORT}/sctp" + - "8080/tcp" + ports: + - "8080:8080/tcp" + networks: + default: + ipv4_address: ${PYHSS_IP} + icscf: + image: docker_kamailio + container_name: icscf + dns: ${DNS_IP} + volumes: + - ./icscf:/mnt/icscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=icscf + depends_on: + - dns + - mysql + - pyhss + expose: + - "${ICSCF_BIND_PORT}/tcp" + - "${ICSCF_BIND_PORT}/sctp" + - "4060/udp" + - "4060/tcp" + networks: + default: + ipv4_address: ${ICSCF_IP} + scscf: + image: docker_kamailio + container_name: scscf + dns: ${DNS_IP} + volumes: + - ./scscf:/mnt/scscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=scscf + depends_on: + - dns + - mysql + - pyhss + expose: + - "${SCSCF_BIND_PORT}/tcp" + - "${SCSCF_BIND_PORT}/sctp" + - "6060/udp" + - "6060/tcp" + networks: + default: + ipv4_address: ${SCSCF_IP} + pcscf: + image: docker_kamailio + container_name: pcscf + dns: ${DNS_IP} + privileged: true + cap_add: + - NET_ADMIN + volumes: + - ./pcscf:/mnt/pcscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=pcscf + - DEPLOY_MODE=4G + depends_on: + - dns + - mysql + - rtpengine + - icscf + - scscf + expose: + - "${PCSCF_BIND_PORT}/tcp" + - "${PCSCF_BIND_PORT}/sctp" + - "5060/tcp" + - "5060/udp" + - "5100-5120/tcp" + - "5100-5120/udp" + - "6100-6120/tcp" + - "6100-6120/udp" + networks: + default: + ipv4_address: ${PCSCF_IP} + smsc: + image: docker_kamailio + container_name: smsc + dns: ${DNS_IP} + volumes: + - ./smsc:/mnt/smsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=smsc + depends_on: + - dns + - mysql + expose: + - "7090/udp" + - "7090/tcp" + networks: + default: + ipv4_address: ${SMSC_IP} + osmomsc: + build: ./osmomsc + image: docker_osmomsc + container_name: osmomsc + volumes: + - ./osmomsc:/mnt/osmomsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=osmomsc + depends_on: + - osmohlr + expose: + - "29118/sctp" + - "2775/tcp" + networks: + default: + ipv4_address: ${OSMOMSC_IP} + osmohlr: + build: ./osmohlr + image: docker_osmohlr + container_name: osmohlr + volumes: + - ./osmohlr:/mnt/osmohlr + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=osmohlr + expose: + - "4222/tcp" + networks: + default: + ipv4_address: ${OSMOHLR_IP} + metrics: + build: ./metrics + image: docker_metrics + container_name: metrics + env_file: + - .env + volumes: + - ./metrics:/mnt/metrics + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9090/tcp" + ports: + - "9090:9090/tcp" + networks: + default: + ipv4_address: ${METRICS_IP} + grafana: + image: grafana/grafana:11.3.0 + container_name: grafana + env_file: + - .env + volumes: + - grafana_data:/var/lib/grafana + - ./grafana/:/etc/grafana/provisioning/ + - ./grafana:/mnt/grafana + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} + #- GF_INSTALL_PLUGINS=${GRAFANA_INSTALL_PLUGINS} + - GF_PATHS_PROVISIONING=/etc/grafana/provisioning + - GF_PATHS_DATA=/var/lib/grafana + - METRICS_IP=${METRICS_IP} + expose: + - "3000/tcp" + ports: + - "3000:3000/tcp" + networks: + default: + ipv4_address: ${GRAFANA_IP} +networks: + default: + name: docker_open5gs_default + ipam: + config: + - subnet: ${TEST_NETWORK} +volumes: + grafana_data: + name: grafana_data + mongodbdata: + name: docker_open5gs_mongodbdata + dbdata: + name: docker_open5gs_dbdata + ocsdbdata: + name: docker_open5gs_ocsdbdata diff --git a/4g-volte-opensips-ims-deploy.yaml b/4g-volte-opensips-ims-deploy.yaml new file mode 100644 index 0000000..25f6eab --- /dev/null +++ b/4g-volte-opensips-ims-deploy.yaml @@ -0,0 +1,483 @@ +services: + mongo: + image: mongo:6.0 + container_name: mongo + command: --bind_ip 0.0.0.0 + env_file: + - .env + volumes: + - mongodbdata:/data/db + - mongodbdata:/data/configdb + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "27017/udp" + - "27017/tcp" + networks: + default: + ipv4_address: ${MONGO_IP} + webui: + image: docker_open5gs + container_name: webui + depends_on: + - mongo + env_file: + - .env + environment: + - COMPONENT_NAME=webui + volumes: + - ./webui:/mnt/webui + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9999/tcp" + ports: + - "9999:9999/tcp" + networks: + default: + ipv4_address: ${WEBUI_IP} + hss: + image: docker_open5gs + container_name: hss + env_file: + - .env + environment: + - COMPONENT_NAME=hss + volumes: + - ./hss:/mnt/hss + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + depends_on: + - mongo + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + networks: + default: + ipv4_address: ${HSS_IP} + sgwc: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwc + env_file: + - .env + environment: + - COMPONENT_NAME=sgwc + volumes: + - ./sgwc:/mnt/sgwc + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2123/udp" + - "8805/udp" + networks: + default: + ipv4_address: ${SGWC_IP} + sgwu: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwu + env_file: + - .env + environment: + - COMPONENT_NAME=sgwu + volumes: + - ./sgwu:/mnt/sgwu + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "8805/udp" + - "2152/udp" + # ports: + # - "2152:2152/udp" + networks: + default: + ipv4_address: ${SGWU_IP} + smf: + image: docker_open5gs + container_name: smf + env_file: + - .env + environment: + - COMPONENT_NAME=smf + - DEPLOY_MODE=4G + volumes: + - ./smf:/mnt/smf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "8805/udp" + - "2123/udp" + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${SMF_IP} + upf: + image: docker_open5gs + depends_on: + - smf + container_name: upf + env_file: + - .env + environment: + - COMPONENT_NAME=upf + volumes: + - ./upf:/mnt/upf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2152/udp" + - "8805/udp" + - "9091/tcp" + cap_add: + - NET_ADMIN + privileged: true + sysctls: + - net.ipv4.ip_forward=1 + networks: + default: + ipv4_address: ${UPF_IP} + mme: + image: docker_open5gs + depends_on: + - hss + - sgwc + - sgwu + - smf + - upf + - osmomsc + container_name: mme + env_file: + - .env + environment: + - COMPONENT_NAME=mme + volumes: + - ./mme:/mnt/mme + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "36412/sctp" + - "2123/udp" + - "9091/tcp" + # ports: + # - "36412:36412/sctp" + networks: + default: + ipv4_address: ${MME_IP} + pcrf: + image: docker_open5gs + container_name: pcrf + env_file: + - .env + environment: + - COMPONENT_NAME=pcrf + depends_on: + - mongo + volumes: + - ./pcrf:/mnt/pcrf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "${PCRF_BIND_PORT}/tcp" + - "${PCRF_BIND_PORT}/sctp" + - "5868/tcp" + - "5868/sctp" + networks: + default: + ipv4_address: ${PCRF_IP} + dns: + build: ./dns + image: docker_dns + container_name: dns + env_file: + - .env + volumes: + - ./dns:/mnt/dns + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "53/udp" + networks: + default: + ipv4_address: ${DNS_IP} + rtpengine: + build: ./rtpengine + image: docker_rtpengine + container_name: rtpengine + privileged: true + env_file: + - .env + volumes: + - ./rtpengine:/mnt/rtpengine + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + cap_add: + - NET_ADMIN + environment: + - TABLE=0 + - INTERFACE=${RTPENGINE_IP} + - LISTEN_NG=${RTPENGINE_IP}:2223 + - PIDFILE=/run/ngcp-rtpengine-daemon.pid + - PORT_MAX=50000 + - PORT_MIN=49000 + - NO_FALLBACK=no + - TOS=184 + expose: + - "2223/udp" + - "49000-50000/udp" + networks: + default: + ipv4_address: ${RTPENGINE_IP} + mysql: + build: ./mysql + image: docker_mysql + container_name: mysql + env_file: + - .env + volumes: + - dbdata:/var/lib/mysql + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3306/tcp" + networks: + default: + ipv4_address: ${MYSQL_IP} + pyhss: + build: ./pyhss + image: docker_pyhss + container_name: pyhss + dns: ${DNS_IP} + volumes: + - ./pyhss:/mnt/pyhss + - ./pyhss/logs:/pyhss/log/ + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + depends_on: + - dns + - mysql + expose: + - "${PYHSS_BIND_PORT}/tcp" + - "${PYHSS_BIND_PORT}/sctp" + - "8080/tcp" + ports: + - "8080:8080/tcp" + networks: + default: + ipv4_address: ${PYHSS_IP} + icscf: + image: docker_opensips + container_name: icscf + dns: ${DNS_IP} + volumes: + - ./opensips_ims_icscf:/mnt/icscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=icscf + depends_on: + - dns + - mysql + - pyhss + expose: + - "${ICSCF_BIND_PORT}/tcp" + - "${ICSCF_BIND_PORT}/sctp" + - "4060/udp" + - "4060/tcp" + networks: + default: + ipv4_address: ${ICSCF_IP} + scscf: + image: docker_opensips + container_name: scscf + dns: ${DNS_IP} + volumes: + - ./opensips_ims_scscf:/mnt/scscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=scscf + depends_on: + - dns + - mysql + - pyhss + expose: + - "${SCSCF_BIND_PORT}/tcp" + - "${SCSCF_BIND_PORT}/sctp" + - "6060/udp" + - "6060/tcp" + networks: + default: + ipv4_address: ${SCSCF_IP} + pcscf: + image: docker_opensips + container_name: pcscf + dns: ${DNS_IP} + privileged: true + cap_add: + - NET_ADMIN + volumes: + - ./opensips_ims_pcscf:/mnt/pcscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=pcscf + - DEPLOY_MODE=4G + depends_on: + - dns + - mysql + - rtpengine + - icscf + - scscf + expose: + - "${PCSCF_BIND_PORT}/tcp" + - "${PCSCF_BIND_PORT}/sctp" + - "5060/tcp" + - "5060/udp" + - "5100-5120/tcp" + - "5100-5120/udp" + - "6100-6120/tcp" + - "6100-6120/udp" + networks: + default: + ipv4_address: ${PCSCF_IP} + smsc: + image: docker_kamailio + container_name: smsc + dns: ${DNS_IP} + volumes: + - ./smsc:/mnt/smsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=smsc + depends_on: + - dns + - mysql + expose: + - "7090/udp" + - "7090/tcp" + networks: + default: + ipv4_address: ${SMSC_IP} + osmomsc: + build: ./osmomsc + image: docker_osmomsc + container_name: osmomsc + volumes: + - ./osmomsc:/mnt/osmomsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=osmomsc + depends_on: + - osmohlr + expose: + - "29118/sctp" + - "2775/tcp" + networks: + default: + ipv4_address: ${OSMOMSC_IP} + osmohlr: + build: ./osmohlr + image: docker_osmohlr + container_name: osmohlr + volumes: + - ./osmohlr:/mnt/osmohlr + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=osmohlr + expose: + - "4222/tcp" + networks: + default: + ipv4_address: ${OSMOHLR_IP} + metrics: + build: ./metrics + image: docker_metrics + container_name: metrics + env_file: + - .env + volumes: + - ./metrics:/mnt/metrics + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9090/tcp" + ports: + - "9090:9090/tcp" + networks: + default: + ipv4_address: ${METRICS_IP} + grafana: + image: grafana/grafana:11.3.0 + container_name: grafana + env_file: + - .env + volumes: + - grafana_data:/var/lib/grafana + - ./grafana/:/etc/grafana/provisioning/ + - ./grafana:/mnt/grafana + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} + #- GF_INSTALL_PLUGINS=${GRAFANA_INSTALL_PLUGINS} + - GF_PATHS_PROVISIONING=/etc/grafana/provisioning + - GF_PATHS_DATA=/var/lib/grafana + - METRICS_IP=${METRICS_IP} + expose: + - "3000/tcp" + ports: + - "3000:3000/tcp" + networks: + default: + ipv4_address: ${GRAFANA_IP} +networks: + default: + ipam: + config: + - subnet: ${TEST_NETWORK} +volumes: + grafana_data: + name: grafana_data + mongodbdata: {} + dbdata: {} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3b06a3c --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2020, Supreeth Herle +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..86b8ff7 --- /dev/null +++ b/README.md @@ -0,0 +1,513 @@ +# docker_open5gs +Quite contrary to the name of the repository, this repository contains docker files to deploy an Over-The-Air (OTA) or RF simulated 4G/5G network using following projects: +- Core Network (4G/5G) - open5gs - https://github.com/open5gs/open5gs +- IMS (VoLTE + VoNR) - kamailio - https://github.com/kamailio/kamailio +- IMS (Only 4G supported i.e. VoLTE) - openSIP IMS CE - https://ce.opensips.org/opensips-ims +- IMS HSS - https://github.com/nickvsnetworking/pyhss +- Osmocom HLR - https://github.com/osmocom/osmo-hlr +- Osmocom MSC - https://github.com/osmocom/osmo-msc +- srsRAN_4G (4G eNB + 4G UE + 5G UE) - https://github.com/srsran/srsRAN_4G +- srsRAN_Project (5G gNB) - https://github.com/srsran/srsRAN_Project +- UERANSIM (5G gNB + 5G UE) - https://github.com/aligungr/UERANSIM +- eUPF (5G UPF) - https://github.com/edgecomllc/eupf +- OpenSIPS IMS - https://github.com/OpenSIPS/opensips +- Sigscale OCS - https://github.com/sigscale/ocs + +## Tested Setup + +Docker host machine + +- Ubuntu 22.04 or above + +Over-The-Air setups: + +- srsRAN_Project gNB using Ettus USRP B210 +- srsRAN_Project (5G gNB) using LibreSDR (USRP B210 clone) +- srsRAN_4G eNB using LimeSDR Mini v1.3 +- srsRAN_4G eNB using LimeSDR-USB +- srsRAN_4G eNB using LibreSDR (USRP B210 clone) + +RF simulated setups: + +- srsRAN_4G (eNB + UE) simulation over ZMQ +- srsRAN_Project (5G gNB) + srsRAN_4G (5G UE) simulation over ZMQ +- UERANSIM (gNB + UE) simulator + +## Prepare Docker images + +* Mandatory requirements: + * [docker-ce](https://docs.docker.com/install/linux/docker-ce/ubuntu) - Version 22.0.5 or above + * [docker compose](https://docs.docker.com/compose) - Version 2.14 or above + +You can either pull the pre-built docker images or build them from the source. + +### Get Pre-built Docker images + +Pull base images: +``` +docker pull ghcr.io/herlesupreeth/docker_open5gs:master +docker tag ghcr.io/herlesupreeth/docker_open5gs:master docker_open5gs + +docker pull ghcr.io/herlesupreeth/docker_grafana:master +docker tag ghcr.io/herlesupreeth/docker_grafana:master docker_grafana + +docker pull ghcr.io/herlesupreeth/docker_metrics:master +docker tag ghcr.io/herlesupreeth/docker_metrics:master docker_metrics +``` + +You can also pull the pre-built images for additional components + +For IMS components: +``` +docker pull ghcr.io/herlesupreeth/docker_osmohlr:master +docker tag ghcr.io/herlesupreeth/docker_osmohlr:master docker_osmohlr + +docker pull ghcr.io/herlesupreeth/docker_osmomsc:master +docker tag ghcr.io/herlesupreeth/docker_osmomsc:master docker_osmomsc + +docker pull ghcr.io/herlesupreeth/docker_pyhss:master +docker tag ghcr.io/herlesupreeth/docker_pyhss:master docker_pyhss + +docker pull ghcr.io/herlesupreeth/docker_kamailio:master +docker tag ghcr.io/herlesupreeth/docker_kamailio:master docker_kamailio + +docker pull ghcr.io/herlesupreeth/docker_mysql:master +docker tag ghcr.io/herlesupreeth/docker_mysql:master docker_mysql + +docker pull ghcr.io/herlesupreeth/docker_opensips:master +docker tag ghcr.io/herlesupreeth/docker_opensips:master docker_opensips +``` + +For srsRAN components: +``` +docker pull ghcr.io/herlesupreeth/docker_srslte:master +docker tag ghcr.io/herlesupreeth/docker_srslte:master docker_srslte + +docker pull ghcr.io/herlesupreeth/docker_srsran:master +docker tag ghcr.io/herlesupreeth/docker_srsran:master docker_srsran +``` + +For UERANSIM components: +``` +docker pull ghcr.io/herlesupreeth/docker_ueransim:master +docker tag ghcr.io/herlesupreeth/docker_ueransim:master docker_ueransim +``` + +For OAI components: +``` +docker pull ghcr.io/herlesupreeth/docker_oai_enb:master +docker tag ghcr.io/herlesupreeth/docker_oai_enb:master docker_oai_enb + +docker pull ghcr.io/herlesupreeth/docker_oai_gnb:master +docker tag ghcr.io/herlesupreeth/docker_oai_gnb:master docker_oai_gnb +``` + +For EUPF component: +``` +docker pull ghcr.io/herlesupreeth/docker_eupf:master +docker tag ghcr.io/herlesupreeth/docker_eupf:master docker_eupf +``` + +For Sigscale OCS component: +``` +docker pull ghcr.io/herlesupreeth/docker_ocs:master +docker tag ghcr.io/herlesupreeth/docker_ocs:master docker_ocs +``` + +### Build Docker images from source +#### Clone repository and build base docker image of open5gs, kamailio, srsRAN_4G, srsRAN_Project, ueransim + +``` +# Build docker images for open5gs EPC/5GC components +git clone https://github.com/herlesupreeth/docker_open5gs +cd docker_open5gs/base +docker build --no-cache --force-rm -t docker_open5gs . + +# Build docker images for kamailio IMS components +cd ../ims_base +docker build --no-cache --force-rm -t docker_kamailio . + +# Build docker images for srsRAN_4G eNB + srsUE (4G+5G) +cd ../srslte +docker build --no-cache --force-rm -t docker_srslte . + +# Build docker images for srsRAN_Project gNB +cd ../srsran +docker build --no-cache --force-rm -t docker_srsran . + +# Build docker images for UERANSIM (gNB + UE) +cd ../ueransim +docker build --no-cache --force-rm -t docker_ueransim . + +# Build docker images for EUPF +cd ../eupf +docker build --no-cache --force-rm -t docker_eupf . + +# Build docker images for OpenSIPS IMS +cd ../opensips_ims_base +docker build --no-cache --force-rm -t docker_opensips . +``` + +#### Build docker images for additional components + +``` +cd .. +set -a +source .env +set +a +sudo ufw disable +sudo sysctl -w net.ipv4.ip_forward=1 +sudo cpupower frequency-set -g performance + +# For 4G deployment only +docker compose -f 4g-volte-deploy.yaml build + +# For 5G deployment only +docker compose -f sa-deploy.yaml build +``` + +## Network and deployment configuration + +The setup can be mainly deployed in two ways: + +1. Single host setup where eNB/gNB and (EPC+IMS)/5GC are deployed on a single host machine +2. Multi host setup where eNB/gNB is deployed on a separate host machine than (EPC+IMS)/5GC + +### Single Host setup configuration +Edit only the following parameters in **.env** as per your setup + +``` +MCC +MNC +DOCKER_HOST_IP --> This is the IP address of the host running your docker setup +UE_IPV4_INTERNET --> Change this to your desired (Not conflicted) UE network ip range for internet APN +UE_IPV4_IMS --> Change this to your desired (Not conflicted) UE network ip range for ims APN +``` + +### Multihost setup configuration + +#### 4G deployment + +###### On the host running the (EPC+IMS) + +Edit only the following parameters in **.env** as per your setup +``` +MCC +MNC +DOCKER_HOST_IP --> This is the IP address of the host running (EPC+IMS) +SGWU_ADVERTISE_IP --> Change this to value of DOCKER_HOST_IP +UE_IPV4_INTERNET --> Change this to your desired (Not conflicted) UE network ip range for internet APN +UE_IPV4_IMS --> Change this to your desired (Not conflicted) UE network ip range for ims APN +``` + +Under **mme** section in docker compose file (**4g-volte-deploy.yaml**), uncomment the following part +``` +... + # ports: + # - "36412:36412/sctp" +... +``` + +Then, uncomment the following part under **sgwu** section +``` +... + # ports: + # - "2152:2152/udp" +... +``` + +###### On the host running the eNB + +Edit only the following parameters in **.env** as per your setup +``` +MCC +MNC +DOCKER_HOST_IP --> This is the IP address of the host running eNB +MME_IP --> Change this to IP address of host running (EPC+IMS) +SRS_ENB_IP --> Change this to the IP address of the host running eNB +``` + +Replace the following part in the docker compose file (**srsenb.yaml**) +``` + networks: + default: + ipv4_address: ${SRS_ENB_IP} +networks: + default: + external: + name: docker_open5gs_default +``` +with +``` + network_mode: host +``` + +#### 5G SA deployment + +###### On the host running the 5GC + +Edit only the following parameters in **.env** as per your setup +``` +MCC +MNC +DOCKER_HOST_IP --> This is the IP address of the host running 5GC +UPF_ADVERTISE_IP --> Change this to value of DOCKER_HOST_IP +UE_IPV4_INTERNET --> Change this to your desired (Not conflicted) UE network ip range for internet APN +UE_IPV4_IMS --> Change this to your desired (Not conflicted) UE network ip range for ims APN +``` + +Under **amf** section in docker compose file (**sa-deploy.yaml**), uncomment the following part +``` +... + # ports: + # - "38412:38412/sctp" +... +``` + +Then, uncomment the following part under **upf** section +``` +... + # ports: + # - "2152:2152/udp" +... +``` + +###### On the host running the gNB + +Edit only the following parameters in **.env** as per your setup +``` +MCC +MNC +DOCKER_HOST_IP --> This is the IP address of the host running gNB +AMF_IP --> Change this to IP address of host running 5GC +SRS_GNB_IP --> Change this to the IP address of the host running gNB +``` + +Replace the following part in the docker compose file (**srsgnb.yaml**) +``` + networks: + default: + ipv4_address: ${SRS_GNB_IP} +networks: + default: + external: + name: docker_open5gs_default +``` +with +``` + network_mode: host +``` + +## Network Deployment + +###### 4G deployment + +``` +# 4G Core Network + IMS + SMS over SGs (uses Kamailio IMS) +docker compose -f 4g-volte-deploy.yaml up + +# 4G Core Network + IMS + SMS over SGs (uses openSIPS IMS) +docker compose -f 4g-volte-opensips-ims-deploy.yaml up + +# srsRAN eNB using SDR (OTA) +docker compose -f srsenb.yaml up -d && docker container attach srsenb + +# srsRAN ZMQ eNB (RF simulated) +docker compose -f srsenb_zmq.yaml up -d && docker container attach srsenb_zmq + +# srsRAN ZMQ 4G UE (RF simulated) +docker compose -f srsue_zmq.yaml up -d && docker container attach srsue_zmq +``` + +###### 5G SA deployment + +``` +# 5G Core Network +docker compose -f sa-deploy.yaml up + +# srsRAN gNB using SDR (OTA) +docker compose -f srsgnb.yaml up -d && docker container attach srsgnb + +# srsRAN ZMQ gNB (RF simulated) +docker compose -f srsgnb_zmq.yaml up -d && docker container attach srsgnb_zmq + +# srsRAN ZMQ 5G UE (RF simulated) +docker compose -f srsue_5g_zmq.yaml up -d && docker container attach srsue_5g_zmq + +# UERANSIM gNB (RF simulated) +docker compose -f nr-gnb.yaml up -d && docker container attach nr_gnb + +# UERANSIM NR-UE (RF simulated) +docker compose -f nr-ue.yaml up -d && docker container attach nr_ue +``` + +## Docker Compose files overview + +This repository provides several Docker Compose files to support different deployment scenarios and components. Below is a summary of the compose files and their purposes: + +| Compose File | Description | +|------------------------------------|----------------------------------------------------------------------------------------------------| +| `4g-volte-deploy.yaml` | Deploys 4G Core Network (EPC) with IMS (VoLTE) using Kamailio. | +| `4g-volte-opensips-ims-deploy.yaml`| Deploys 4G Core Network with IMS using OpenSIPS. | +| `sa-deploy.yaml` | Deploys 5G Standalone (SA) Core Network (5GC). | +| `sa-vonr-deploy.yaml` | Deploys 5G Standalone (SA) Core Network (5GC) with IMS (VoNR) using Kamailio. | +| `srsenb.yaml` | Deploys srsRAN 4G eNB for OTA setups using SDR hardware. | +| `srsenb_zmq.yaml` | Deploys srsRAN 4G eNB for RF simulated setups over ZMQ. | +| `srsue_zmq.yaml` | Deploys srsRAN 4G UE for RF simulated setups over ZMQ. | +| `srsran.yaml` | Deploys srsRAN_4G components (eNB/UE). | +| `srsgnb.yaml` | Deploys srsRAN 5G gNB for OTA setups using SDR hardware. | +| `srsgnb_zmq.yaml` | Deploys srsRAN 5G gNB for RF simulated setups over ZMQ. | +| `srsue_5g_zmq.yaml` | Deploys srsRAN 5G UE for RF simulated setups over ZMQ. | +| `nr-gnb.yaml` | Deploys UERANSIM 5G gNB simulator. | +| `nr-ue.yaml` | Deploys UERANSIM 5G UE simulator. | +| `4g-volte-ocs-deploy.yaml` | Deploys 4G Core Network (EPC) + Sigscale OCS with IMS (VoLTE) using Kamailio. | +| `4g-external-ims-deploy.yaml` | Deploys 4G Core Network (EPC) + Sigscale OCS + PyHSS (IMS) with no IMS components. | +| `sa-vonr-ibcf-deploy.yaml` | Deploys 5G Standalone (SA) Core Network (5GC) + IMS (VoNR) using Kamailio + IBCF. | +| `sa-vonr-opensips-ims-deploy.yaml` | Deploys 5G Standalone (SA) Core Network (5GC) with IMS (VoNR) using OpenSIPS (Experimental). | +| `oaienb.yaml` | Deploys OAI eNB for OTA setups using SDR hardware (Untested and Unmaintained). | +| `oaignb.yaml` | Deploys OAI 5G gNB for OTA setups using SDR hardware (Untested and Unmaintained). | + +## Provisioning of SIM information + +### Provisioning of SIM information in open5gs HSS as follows: + +Open (http://:9999) in a web browser, where is the IP of the machine/VM running the open5gs containers. Login with following credentials +``` +Username : admin +Password : 1423 +``` + +Using Web UI, add a subscriber + +#### or using cli + +``` +sudo docker exec -it hss misc/db/open5gs-dbctl add 001010123456790 8baf473f2f8fd09487cccbd7097c6862 8E27B6AF0E692E750F32667A3B14605D +``` + + +### Provisioning of IMSI and MSISDN with OsmoHLR as follows: + +1. First, telnet to OsmoHLR from host machine using the following command: + +``` +$ telnet 172.22.0.32 4258 + +OsmoHLR> enable +OsmoHLR# +``` + +2. Then, register the subscriber information as in following example: + +``` +OsmoHLR# subscriber imsi 001010123456790 create +OsmoHLR# subscriber imsi 001010123456790 update msisdn 9076543210 +``` + +**Replace IMSI and MSISDN as per your programmed SIM** + + +### Provisioning of SIM information in pyHSS is as follows: + +1. Goto http://:8080/docs/ +2. Select **apn** -> **Create new APN** -> Press on **Try it out**. Then, in payload section use the below JSON and then press **Execute** + +``` +{ + "apn": "internet", + "apn_ambr_dl": 0, + "apn_ambr_ul": 0 +} +``` + +Take note of **apn_id** specified in **Response body** under **Server response** for **internet** APN + +Repeat creation step for following payload + +``` +{ + "apn": "ims", + "apn_ambr_dl": 0, + "apn_ambr_ul": 0 +} +``` + +Take note of **apn_id** specified in **Response body** under **Server response** for **ims** APN + +**Execute this step of APN creation only once** + +3. Next, select **auc** -> **Create new AUC** -> Press on **Try it out**. Then, in payload section use the below example JSON to fill in ki, opc and amf for your SIM and then press **Execute** + +``` +{ + "ki": "8baf473f2f8fd09487cccbd7097c6862", + "opc": "8E27B6AF0E692E750F32667A3B14605D", + "amf": "8000", + "sqn": 0, + "imsi": "001010123456790" +} +``` + +Take note of **auc_id** specified in **Response body** under **Server response** + +**Replace imsi, ki, opc and amf as per your programmed SIM** + +4. Next, select **subscriber** -> **Create new SUBSCRIBER** -> Press on **Try it out**. Then, in payload section use the below example JSON to fill in imsi, auc_id and apn_list for your SIM and then press **Execute** + +``` +{ + "imsi": "001010123456790", + "enabled": true, + "auc_id": 1, + "default_apn": 1, + "apn_list": "1,2", + "msisdn": "9076543210", + "ue_ambr_dl": 0, + "ue_ambr_ul": 0 +} +``` + +- **auc_id** is the ID of the **AUC** created in the previous steps +- **default_apn** is the ID of the **internet** APN created in the previous steps +- **apn_list** is the comma separated list of APN IDs allowed for the UE i.e. APN ID for **internet** and **ims** APN created in the previous steps + +**Replace imsi and msisdn as per your programmed SIM** + +5. Finally, select **ims_subscriber** -> **Create new IMS SUBSCRIBER** -> Press on **Try it out**. Then, in payload section use the below example JSON to fill in imsi, msisdn, msisdn_list, scscf_peer, scscf_realm and scscf for your SIM/deployment and then press **Execute** + +``` +{ + "imsi": "001010123456790", + "msisdn": "9076543210", + "sh_profile": "string", + "scscf_peer": "scscf.ims.mnc001.mcc001.3gppnetwork.org", + "msisdn_list": "[9076543210]", + "ifc_path": "default_ifc.xml", + "scscf": "sip:scscf.ims.mnc001.mcc001.3gppnetwork.org:6060", + "scscf_realm": "ims.mnc001.mcc001.3gppnetwork.org" +} +``` + +**Replace imsi, msisdn and msisdn_list as per your programmed SIM** + +**Replace scscf_peer, scscf and scscf_realm as per your deployment** + +### Provisioning of Diameter Peer + Subscriber information in Sigscale OCS as follows (Skip if OCS is not deployed): + +1. Goto http://:8083 +2. Login with following credentials +``` +Username : admin +Password : admin +``` +3. Configure SMF as Diameter Peer as mentioned here - https://sigscale.atlassian.net/wiki/spaces/SO/pages/3833890/How-To+with+OCS#Add-an-DIAMETER-client-(DRA%2FSGSN%2FPGW) + + NOTE: IP address must be equal to **SMF_IP** in **.env** file and the Protocol must be set to Diameter. + +4. Subscriber information can be provisioned as mentioned here - https://sigscale.atlassian.net/wiki/spaces/SO/pages/3833890/How-To+with+OCS#Add-a-subscriber + + NOTE: The IMSI and the MSISDN must be equal to the one provisioned in open5gs HSS and/or pyHSS. + + +## Not supported +- IPv6 usage in Docker diff --git a/amf/amf.yaml b/amf/amf.yaml new file mode 100644 index 0000000..ee2ed5d --- /dev/null +++ b/amf/amf.yaml @@ -0,0 +1,59 @@ +logger: + file: + path: /open5gs/install/var/log/open5gs/amf.log + +sbi: + server: + no_tls: true + client: + no_tls: true + +global: + max: + ue: MAX_NUM_UE + +amf: + sbi: + server: + - address: AMF_IP + port: 7777 + client: + nrf: + - uri: http://NRF_IP:7777 + scp: + - uri: http://SCP_IP:7777 + ngap: + server: + - address: AMF_IP + guami: + - plmn_id: + mcc: MCC + mnc: MNC + amf_id: + region: 2 + set: 1 + tai: + - plmn_id: + mcc: MCC + mnc: MNC + tac: TAC + plmn_support: + - plmn_id: + mcc: MCC + mnc: MNC + s_nssai: + - sst: 1 + security: + integrity_order : [ NIA2, NIA1, NIA0 ] + ciphering_order : [ NEA0, NEA1, NEA2 ] + network_name: + full: Open5GS + amf_name: open5gs-amf0 + metrics: + server: + - address: AMF_IP + port: 9091 + time: + t3512: + value: 540 + diff --git a/amf/amf_init.sh b/amf/amf_init.sh new file mode 100755 index 0000000..47a928a --- /dev/null +++ b/amf/amf_init.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +cp /mnt/amf/amf.yaml install/etc/open5gs +sed -i 's|AMF_IP|'$AMF_IP'|g' install/etc/open5gs/amf.yaml +sed -i 's|SCP_IP|'$SCP_IP'|g' install/etc/open5gs/amf.yaml +sed -i 's|NRF_IP|'$NRF_IP'|g' install/etc/open5gs/amf.yaml +sed -i 's|MNC|'$MNC'|g' install/etc/open5gs/amf.yaml +sed -i 's|MCC|'$MCC'|g' install/etc/open5gs/amf.yaml +sed -i 's|TAC|'$TAC'|g' install/etc/open5gs/amf.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/amf.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/ausf/ausf.yaml b/ausf/ausf.yaml new file mode 100644 index 0000000..43ad006 --- /dev/null +++ b/ausf/ausf.yaml @@ -0,0 +1,24 @@ +logger: + file: + path: /open5gs/install/var/log/open5gs/ausf.log + +sbi: + server: + no_tls: true + client: + no_tls: true + +global: + max: + ue: MAX_NUM_UE + +ausf: + sbi: + server: + - address: AUSF_IP + port: 7777 + client: + nrf: + - uri: http://NRF_IP:7777 + scp: + - uri: http://SCP_IP:7777 diff --git a/ausf/ausf_init.sh b/ausf/ausf_init.sh new file mode 100755 index 0000000..d9d0704 --- /dev/null +++ b/ausf/ausf_init.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +cp /mnt/ausf/ausf.yaml install/etc/open5gs +sed -i 's|AUSF_IP|'$AUSF_IP'|g' install/etc/open5gs/ausf.yaml +sed -i 's|SCP_IP|'$SCP_IP'|g' install/etc/open5gs/ausf.yaml +sed -i 's|NRF_IP|'$NRF_IP'|g' install/etc/open5gs/ausf.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/ausf.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/base/Dockerfile b/base/Dockerfile new file mode 100644 index 0000000..ff423b3 --- /dev/null +++ b/base/Dockerfile @@ -0,0 +1,133 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM ubuntu:focal as builder + +ENV DEBIAN_FRONTEND=noninteractive + +# Install updates and dependencies +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + python3-pip \ + python3-setuptools \ + python3-wheel \ + ninja-build \ + build-essential \ + flex \ + bison \ + git \ + cmake \ + libsctp-dev \ + libgnutls28-dev \ + libgcrypt-dev \ + libssl-dev \ + libidn11-dev \ + libmongoc-dev \ + libbson-dev \ + libyaml-dev \ + meson \ + mongodb \ + curl \ + gnupg \ + ca-certificates \ + libmicrohttpd-dev \ + libcurl4-gnutls-dev \ + libnghttp2-dev \ + libtins-dev \ + libidn11-dev \ + libtalloc-dev + +RUN mkdir -p /etc/apt/keyrings +RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ + NODE_MAJOR=20 && \ + echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ + apt-get update && apt install nodejs -y + +# Get open5gs code and install +RUN git clone --recursive https://github.com/open5gs/open5gs && cd open5gs && \ + git checkout 8e286b67f1ccdd1d6bc31d36b553991337583f33 && meson build --prefix=`pwd`/install && \ + ninja -C build && cd build && ninja install && \ + mkdir -p /open5gs/install/include + +# Building WebUI of open5gs +RUN cd open5gs/webui && npm ci + +# Build final image +FROM ubuntu:focal + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + curl \ + ca-certificates \ + libssl-dev \ + libyaml-dev \ + libmicrohttpd-dev \ + libmongoc-dev \ + libsctp-dev \ + libcurl4-gnutls-dev \ + libtins-dev \ + libidn11-dev \ + libtalloc-dev \ + netbase \ + ifupdown \ + net-tools \ + iputils-ping \ + python3-setuptools \ + python3-wheel \ + python3-pip \ + iptables \ + iperf \ + iperf3 \ + traceroute \ + tcpdump \ + mongodb-clients \ + gnupg && \ + apt-get autoremove -y && apt-get autoclean + +RUN pip3 install click + +RUN mkdir -p /etc/apt/keyrings +RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ + NODE_MAJOR=20 && \ + echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ + apt-get update && apt install nodejs -y + +RUN update-ca-certificates + +COPY --from=builder /open5gs/install/bin /open5gs/install/bin +COPY --from=builder /open5gs/install/etc /open5gs/install/etc +COPY --from=builder /open5gs/install/include /open5gs/install/include +COPY --from=builder /open5gs/install/lib /open5gs/install/lib +COPY --from=builder /open5gs/webui /open5gs/webui +COPY --from=builder /open5gs/misc/db /open5gs/misc/db + +# Set the working directory to open5gs +WORKDIR open5gs + +COPY open5gs_init.sh / +CMD /open5gs_init.sh diff --git a/base/open5gs_init.sh b/base/open5gs_init.sh new file mode 100755 index 0000000..b74a7e4 --- /dev/null +++ b/base/open5gs_init.sh @@ -0,0 +1,102 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, this +# list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export LD_LIBRARY_PATH=/open5gs/install/lib/$(uname -m)-linux-gnu + +if [[ -z "$COMPONENT_NAME" ]]; then + echo "Error: COMPONENT_NAME environment variable not set"; exit 1; +elif [[ "$COMPONENT_NAME" =~ ^(amf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/amf/${COMPONENT_NAME}_init.sh && \ + cd install/bin && ./open5gs-amfd +elif [[ "$COMPONENT_NAME" =~ ^(ausf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/ausf/${COMPONENT_NAME}_init.sh && \ + cd install/bin && ./open5gs-ausfd +elif [[ "$COMPONENT_NAME" =~ ^(bsf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/bsf/${COMPONENT_NAME}_init.sh && sleep 10 && \ + cd install/bin && ./open5gs-bsfd +elif [[ "$COMPONENT_NAME" =~ ^(hss[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/hss/${COMPONENT_NAME}_init.sh && \ + cd install/bin && sleep 10 && ./open5gs-hssd +elif [[ "$COMPONENT_NAME" =~ ^(mme[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/mme/${COMPONENT_NAME}_init.sh && \ + cd install/bin && ./open5gs-mmed +elif [[ "$COMPONENT_NAME" =~ ^(nrf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/nrf/${COMPONENT_NAME}_init.sh && \ + cd install/bin && ./open5gs-nrfd +elif [[ "$COMPONENT_NAME" =~ ^(scp[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/scp/${COMPONENT_NAME}_init.sh && \ + cd install/bin && ./open5gs-scpd +elif [[ "$COMPONENT_NAME" =~ ^(nssf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/nssf/${COMPONENT_NAME}_init.sh && \ + cd install/bin && ./open5gs-nssfd +elif [[ "$COMPONENT_NAME" =~ ^(pcf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/pcf/${COMPONENT_NAME}_init.sh && sleep 10 && \ + cd install/bin && ./open5gs-pcfd +elif [[ "$COMPONENT_NAME" =~ ^(pcrf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/pcrf/${COMPONENT_NAME}_init.sh && sleep 10 && \ + cd install/bin && ./open5gs-pcrfd +elif [[ "$COMPONENT_NAME" =~ ^(sgwc[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/sgwc/${COMPONENT_NAME}_init.sh && \ + cd install/bin && ./open5gs-sgwcd +elif [[ "$COMPONENT_NAME" =~ ^(sgwu[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/sgwu/${COMPONENT_NAME}_init.sh && \ + cd install/bin && ./open5gs-sgwud +elif [[ "$COMPONENT_NAME" =~ ^(smf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/smf/${COMPONENT_NAME}_init.sh && \ + cd install/bin && ./open5gs-smfd +elif [[ "$COMPONENT_NAME" =~ ^(udm[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/udm/${COMPONENT_NAME}_init.sh && \ + cd install/bin && ./open5gs-udmd +elif [[ "$COMPONENT_NAME" =~ ^(udr[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/udr/${COMPONENT_NAME}_init.sh && sleep 10 && \ + cd install/bin && ./open5gs-udrd +elif [[ "$COMPONENT_NAME" =~ ^(upf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/upf/${COMPONENT_NAME}_init.sh && \ + cd install/bin && ./open5gs-upfd +elif [[ "$COMPONENT_NAME" =~ ^(webui) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + sleep 10 && /mnt/webui/webui_init.sh +else + echo "Error: Invalid component name: '$COMPONENT_NAME'" +fi diff --git a/bsf/bsf.yaml b/bsf/bsf.yaml new file mode 100644 index 0000000..401b37b --- /dev/null +++ b/bsf/bsf.yaml @@ -0,0 +1,26 @@ +db_uri: mongodb://MONGO_IP/open5gs + +logger: + file: + path: /open5gs/install/var/log/open5gs/bsf.log + +sbi: + server: + no_tls: true + client: + no_tls: true + +global: + max: + ue: MAX_NUM_UE + +bsf: + sbi: + server: + - address: BSF_IP + port: 7777 + client: + nrf: + - uri: http://NRF_IP:7777 + scp: + - uri: http://SCP_IP:7777 diff --git a/bsf/bsf_init.sh b/bsf/bsf_init.sh new file mode 100755 index 0000000..74930b7 --- /dev/null +++ b/bsf/bsf_init.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export DB_URI="mongodb://${MONGO_IP}/open5gs" + +cp /mnt/bsf/bsf.yaml install/etc/open5gs +sed -i 's|BSF_IP|'$BSF_IP'|g' install/etc/open5gs/bsf.yaml +sed -i 's|SCP_IP|'$SCP_IP'|g' install/etc/open5gs/bsf.yaml +sed -i 's|NRF_IP|'$NRF_IP'|g' install/etc/open5gs/bsf.yaml +sed -i 's|MONGO_IP|'$MONGO_IP'|g' install/etc/open5gs/bsf.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/bsf.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/open5gs_hss_cx/.custom_env b/custom_deployments/open5gs_hss_cx/.custom_env new file mode 100644 index 0000000..c699424 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/.custom_env @@ -0,0 +1,149 @@ +# Set proper timezone to sync times between docker host and containers +#TZ=Europe/Berlin + +MCC=001 +MNC=01 +TAC=1 + +TEST_NETWORK=172.22.0.0/24 +DOCKER_HOST_IP=192.168.1.223 + +# MONGODB +MONGO_IP=172.22.0.2 + +# HSS - open5gs +HSS_IP=172.22.0.3 +HSS_BIND_PORT=3875 + +# PCRF +PCRF_IP=172.22.0.4 +PCRF_BIND_PORT=3873 + +# SGW +SGWC_IP=172.22.0.5 +SGWU_IP=172.22.0.6 +SGWU_ADVERTISE_IP=172.22.0.6 + +# SMF +SMF_IP=172.22.0.7 +SMF_DNS1=8.8.8.8 +SMF_DNS2=8.8.4.4 + +# UPF +UPF_IP=172.22.0.8 +UPF_ADVERTISE_IP=172.22.0.8 +# Allowed values for UPF_TUNTAP_MODE are 'tun' or 'tap' +# If 'tap' is used as IF mode, then UPF_INTERNET_APN_IF_NAME and UPF_IMS_APN_IF_NAME must contain string 'tap' +UPF_TUNTAP_MODE=tun +UPF_INTERNET_APN_IF_NAME=ogstun +UPF_IMS_APN_IF_NAME=ogstun2 + +# MME +MME_IP=172.22.0.9 + +# AMF +AMF_IP=172.22.0.10 + +# AUSF +AUSF_IP=172.22.0.11 + +# NRF +NRF_IP=172.22.0.12 + +# UDM +UDM_IP=172.22.0.13 + +# UDR +UDR_IP=172.22.0.14 + +# IMS DNS +DNS_IP=172.22.0.15 + +# RTPENGINE +RTPENGINE_IP=172.22.0.16 + +# MYSQL +MYSQL_IP=172.22.0.17 + +# ICSCF +ICSCF_IP=172.22.0.19 +ICSCF_BIND_PORT=3869 + +# SCSCF +SCSCF_IP=172.22.0.20 +SCSCF_BIND_PORT=3870 + +# PCSCF +PCSCF_IP=172.22.0.21 +PCSCF_BIND_PORT=3871 + +# SRSLTE ENB +SRS_ENB_IP=172.22.0.22 + +# UERANSIM +NR_GNB_IP=172.22.0.23 +NR_UE_IP=172.22.0.24 + +UE1_IMEI=356938035643803 +UE1_IMEISV=4370816125816151 +UE1_IMSI=001011234567895 +UE1_KI=8baf473f2f8fd09487cccbd7097c6862 +UE1_OP=11111111111111111111111111111111 +UE1_AMF=8000 + +# OAI ENB +OAI_ENB_IP=172.22.0.25 + +# OPEN5GS WEBUI +WEBUI_IP=172.22.0.26 + +# PCF +PCF_IP=172.22.0.27 + +# NSSF +NSSF_IP=172.22.0.28 + +# BSF +BSF_IP=172.22.0.29 + +# ENTITLEMENT SERVER +ENTITLEMENT_SERVER_IP=172.22.0.30 + +# OSMOMSC +OSMOMSC_IP=172.22.0.31 + +# OSMOHLR +OSMOHLR_IP=172.22.0.32 + +# SMSC +SMSC_IP=172.22.0.33 + +# SRSLTE UE +SRS_UE_IP=172.22.0.34 + +# SCP +SCP_IP=172.22.0.35 + +# METRICS +METRICS_IP=172.22.0.36 + +# SRSRAN GNB +SRS_GNB_IP=172.22.0.37 + +# GRAFANA +GRAFANA_IP=172.22.0.39 +GRAFANA_USERNAME=open5gs +GRAFANA_PASSWORD=open5gs + +# OCS +OCS_IP=172.22.0.40 +OCS_BIND_PORT=3872 + +# UE IPv4 Subnet Range for APN=internet +UE_IPV4_INTERNET=192.168.100.0/24 + +# UE IPv4 Subnet Range for APN=ims +UE_IPV4_IMS=192.168.101.0/24 + +# Maximum Number of UEs +MAX_NUM_UE=1024 diff --git a/custom_deployments/open5gs_hss_cx/4g-external-ims-deploy.yaml b/custom_deployments/open5gs_hss_cx/4g-external-ims-deploy.yaml new file mode 100644 index 0000000..3f9e150 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/4g-external-ims-deploy.yaml @@ -0,0 +1,336 @@ +services: + mongo: + image: mongo:6.0 + container_name: mongo + command: --bind_ip 0.0.0.0 + env_file: + - .custom_env + volumes: + - mongodbdata:/data/db + - mongodbdata:/data/configdb + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "27017/udp" + - "27017/tcp" + networks: + default: + ipv4_address: ${MONGO_IP} + webui: + image: docker_open5gs + container_name: webui + depends_on: + - mongo + env_file: + - .custom_env + environment: + - COMPONENT_NAME=webui + volumes: + - ../../webui:/mnt/webui + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9999/tcp" + ports: + - "9999:9999/tcp" + networks: + default: + ipv4_address: ${WEBUI_IP} + hss: + image: docker_open5gs + container_name: hss + env_file: + - .custom_env + environment: + - COMPONENT_NAME=hss + volumes: + - ./hss:/mnt/hss + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + depends_on: + - mongo + expose: + - "${HSS_BIND_PORT}/tcp" + - "${HSS_BIND_PORT}/sctp" + - "5868/tcp" + - "5868/sctp" + # ports: + # - "${HSS_BIND_PORT}:${HSS_BIND_PORT}/sctp" + # - "${HSS_BIND_PORT}:${HSS_BIND_PORT}/tcp" + networks: + default: + ipv4_address: ${HSS_IP} + sgwc: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwc + env_file: + - .custom_env + environment: + - COMPONENT_NAME=sgwc + volumes: + - ../../sgwc:/mnt/sgwc + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2123/udp" + - "8805/udp" + networks: + default: + ipv4_address: ${SGWC_IP} + sgwu: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwu + env_file: + - .custom_env + environment: + - COMPONENT_NAME=sgwu + volumes: + - ../../sgwu:/mnt/sgwu + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "8805/udp" + - "2152/udp" + # ports: + # - "${SGWU_ADVERTISE_IP}:2152:2152/udp" + networks: + default: + ipv4_address: ${SGWU_IP} + smf: + image: docker_open5gs + container_name: smf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=smf + - DEPLOY_MODE=4G + volumes: + - ../../smf:/mnt/smf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "8805/udp" + - "2123/udp" + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${SMF_IP} + upf: + image: docker_open5gs + depends_on: + - smf + container_name: upf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=upf + volumes: + - ../../upf:/mnt/upf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2152/udp" + - "8805/udp" + - "9091/tcp" + cap_add: + - NET_ADMIN + privileged: true + # sysctls: + # - net.ipv4.ip_forward=1 + # - net.ipv6.conf.all.disable_ipv6=0 + network_mode: host + mme: + image: docker_open5gs + depends_on: + - hss + - sgwc + - sgwu + - smf + - upf + - osmomsc + container_name: mme + env_file: + - .custom_env + environment: + - COMPONENT_NAME=mme + volumes: + - ./mme:/mnt/mme + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "36412/sctp" + - "2123/udp" + - "9091/tcp" + # ports: + # - "36412:36412/sctp" + networks: + default: + ipv4_address: ${MME_IP} + pcrf: + image: docker_open5gs + container_name: pcrf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=pcrf + depends_on: + - mongo + volumes: + - ../../pcrf:/mnt/pcrf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "${PCRF_BIND_PORT}/tcp" + - "${PCRF_BIND_PORT}/sctp" + - "5868/tcp" + - "5868/sctp" + # ports: + # - "${PCRF_BIND_PORT}:${PCRF_BIND_PORT}/sctp" + # - "${PCRF_BIND_PORT}:${PCRF_BIND_PORT}/tcp" + networks: + default: + ipv4_address: ${PCRF_IP} + dns: + build: ./dns + image: docker_dns + container_name: dns + env_file: + - .custom_env + volumes: + - ./dns:/mnt/dns + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "53/udp" + networks: + default: + ipv4_address: ${DNS_IP} + mysql: + build: ../../mysql + image: docker_mysql + container_name: mysql + env_file: + - .custom_env + volumes: + - dbdata:/var/lib/mysql + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3306/tcp" + networks: + default: + ipv4_address: ${MYSQL_IP} + osmomsc: + build: ../../osmomsc + image: docker_osmomsc + container_name: osmomsc + volumes: + - ../../osmomsc:/mnt/osmomsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=osmomsc + depends_on: + - osmohlr + expose: + - "29118/sctp" + - "2775/tcp" + networks: + default: + ipv4_address: ${OSMOMSC_IP} + osmohlr: + build: ../../osmohlr + image: docker_osmohlr + container_name: osmohlr + volumes: + - ../../osmohlr:/mnt/osmohlr + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=osmohlr + expose: + - "4222/tcp" + networks: + default: + ipv4_address: ${OSMOHLR_IP} + metrics: + build: ../../metrics + image: docker_metrics + container_name: metrics + env_file: + - .custom_env + volumes: + - ../../metrics:/mnt/metrics + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9090/tcp" + ports: + - "9090:9090/tcp" + networks: + default: + ipv4_address: ${METRICS_IP} + grafana: + image: grafana/grafana:11.3.0 + container_name: grafana + env_file: + - .custom_env + volumes: + - grafana_data:/var/lib/grafana + - ../../grafana/:/etc/grafana/provisioning/ + - ../../grafana:/mnt/grafana + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} + #- GF_INSTALL_PLUGINS=${GRAFANA_INSTALL_PLUGINS} + - GF_PATHS_PROVISIONING=/etc/grafana/provisioning + - GF_PATHS_DATA=/var/lib/grafana + - METRICS_IP=${METRICS_IP} + expose: + - "3000/tcp" + ports: + - "3000:3000/tcp" + networks: + default: + ipv4_address: ${GRAFANA_IP} +networks: + default: + name: docker_open5gs_default + ipam: + config: + - subnet: ${TEST_NETWORK} +volumes: + grafana_data: + name: grafana_data + mongodbdata: + name: docker_open5gs_mongodbdata + dbdata: + name: docker_open5gs_dbdata diff --git a/custom_deployments/open5gs_hss_cx/4g-volte-deploy.yaml b/custom_deployments/open5gs_hss_cx/4g-volte-deploy.yaml new file mode 100644 index 0000000..f790f44 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/4g-volte-deploy.yaml @@ -0,0 +1,464 @@ +services: + mongo: + image: mongo:6.0 + container_name: mongo + command: --bind_ip 0.0.0.0 + env_file: + - .custom_env + volumes: + - mongodbdata:/data/db + - mongodbdata:/data/configdb + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "27017/udp" + - "27017/tcp" + networks: + default: + ipv4_address: ${MONGO_IP} + webui: + image: docker_open5gs + container_name: webui + depends_on: + - mongo + env_file: + - .custom_env + environment: + - COMPONENT_NAME=webui + volumes: + - ../../webui:/mnt/webui + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9999/tcp" + ports: + - "9999:9999/tcp" + networks: + default: + ipv4_address: ${WEBUI_IP} + hss: + image: docker_open5gs + container_name: hss + env_file: + - .custom_env + environment: + - COMPONENT_NAME=hss + volumes: + - ./hss:/mnt/hss + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + depends_on: + - mongo + expose: + - "${HSS_BIND_PORT}/tcp" + - "${HSS_BIND_PORT}/sctp" + - "5868/tcp" + - "5868/sctp" + networks: + default: + ipv4_address: ${HSS_IP} + sgwc: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwc + env_file: + - .custom_env + environment: + - COMPONENT_NAME=sgwc + volumes: + - ../../sgwc:/mnt/sgwc + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2123/udp" + - "8805/udp" + networks: + default: + ipv4_address: ${SGWC_IP} + sgwu: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwu + env_file: + - .custom_env + environment: + - COMPONENT_NAME=sgwu + volumes: + - ../../sgwu:/mnt/sgwu + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "8805/udp" + - "2152/udp" + # ports: + # - "2152:2152/udp" + networks: + default: + ipv4_address: ${SGWU_IP} + smf: + image: docker_open5gs + container_name: smf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=smf + - DEPLOY_MODE=4G + volumes: + - ../../smf:/mnt/smf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/udp" + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "8805/udp" + - "2123/udp" + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${SMF_IP} + upf: + image: docker_open5gs + depends_on: + - smf + container_name: upf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=upf + volumes: + - ../../upf:/mnt/upf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2152/udp" + - "8805/udp" + - "9091/tcp" + cap_add: + - NET_ADMIN + privileged: true + sysctls: + - net.ipv4.ip_forward=1 + networks: + default: + ipv4_address: ${UPF_IP} + mme: + image: docker_open5gs + depends_on: + - hss + - sgwc + - sgwu + - smf + - upf + - osmomsc + container_name: mme + env_file: + - .custom_env + environment: + - COMPONENT_NAME=mme + volumes: + - ./mme:/mnt/mme + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/udp" + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "36412/sctp" + - "2123/udp" + - "9091/tcp" + # ports: + # - "36412:36412/sctp" + networks: + default: + ipv4_address: ${MME_IP} + pcrf: + image: docker_open5gs + container_name: pcrf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=pcrf + depends_on: + - mongo + volumes: + - ../../pcrf:/mnt/pcrf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "${PCRF_BIND_PORT}/tcp" + - "${PCRF_BIND_PORT}/sctp" + - "5868/tcp" + - "5868/sctp" + networks: + default: + ipv4_address: ${PCRF_IP} + dns: + build: ./dns + image: docker_dns + container_name: dns + env_file: + - .custom_env + volumes: + - ./dns:/mnt/dns + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "53/udp" + networks: + default: + ipv4_address: ${DNS_IP} + rtpengine: + build: ../../rtpengine + image: docker_rtpengine + container_name: rtpengine + privileged: true + env_file: + - .custom_env + volumes: + - ../../rtpengine:/mnt/rtpengine + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + cap_add: + - NET_ADMIN + environment: + - TABLE=0 + - INTERFACE=${RTPENGINE_IP} + - LISTEN_NG=${RTPENGINE_IP}:2223 + - PIDFILE=/run/ngcp-rtpengine-daemon.pid + - PORT_MAX=50000 + - PORT_MIN=49000 + - NO_FALLBACK=no + - TOS=184 + expose: + - "2223/udp" + - "49000-50000/udp" + networks: + default: + ipv4_address: ${RTPENGINE_IP} + mysql: + build: ../../mysql + image: docker_mysql + container_name: mysql + env_file: + - .custom_env + volumes: + - dbdata:/var/lib/mysql + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3306/tcp" + networks: + default: + ipv4_address: ${MYSQL_IP} + icscf: + image: docker_kamailio + container_name: icscf + dns: ${DNS_IP} + volumes: + - ./icscf:/mnt/icscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=icscf + depends_on: + - dns + - mysql + - hss + expose: + - "${ICSCF_BIND_PORT}/tcp" + - "${ICSCF_BIND_PORT}/sctp" + - "4060/udp" + - "4060/tcp" + networks: + default: + ipv4_address: ${ICSCF_IP} + scscf: + image: docker_kamailio + container_name: scscf + dns: ${DNS_IP} + volumes: + - ./scscf:/mnt/scscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=scscf + depends_on: + - dns + - mysql + - hss + expose: + - "${SCSCF_BIND_PORT}/tcp" + - "${SCSCF_BIND_PORT}/sctp" + - "6060/udp" + - "6060/tcp" + networks: + default: + ipv4_address: ${SCSCF_IP} + pcscf: + image: docker_kamailio + container_name: pcscf + dns: ${DNS_IP} + privileged: true + cap_add: + - NET_ADMIN + volumes: + - ../../pcscf:/mnt/pcscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=pcscf + - DEPLOY_MODE=4G + depends_on: + - dns + - mysql + - rtpengine + - icscf + - scscf + expose: + - "${PCSCF_BIND_PORT}/tcp" + - "${PCSCF_BIND_PORT}/sctp" + - "5060/tcp" + - "5060/udp" + - "5100-5120/tcp" + - "5100-5120/udp" + - "6100-6120/tcp" + - "6100-6120/udp" + networks: + default: + ipv4_address: ${PCSCF_IP} + smsc: + image: docker_kamailio + container_name: smsc + dns: ${DNS_IP} + volumes: + - ../../smsc:/mnt/smsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=smsc + depends_on: + - dns + - mysql + expose: + - "7090/udp" + - "7090/tcp" + networks: + default: + ipv4_address: ${SMSC_IP} + osmomsc: + build: ../../osmomsc + image: docker_osmomsc + container_name: osmomsc + volumes: + - ../../osmomsc:/mnt/osmomsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=osmomsc + depends_on: + - osmohlr + expose: + - "29118/sctp" + - "2775/tcp" + networks: + default: + ipv4_address: ${OSMOMSC_IP} + osmohlr: + build: ../../osmohlr + image: docker_osmohlr + container_name: osmohlr + volumes: + - ../../osmohlr:/mnt/osmohlr + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=osmohlr + expose: + - "4222/tcp" + networks: + default: + ipv4_address: ${OSMOHLR_IP} + metrics: + build: ../../metrics + image: docker_metrics + container_name: metrics + env_file: + - .custom_env + volumes: + - ../../metrics:/mnt/metrics + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9090/tcp" + ports: + - "9090:9090/tcp" + networks: + default: + ipv4_address: ${METRICS_IP} + grafana: + image: grafana/grafana:11.3.0 + container_name: grafana + env_file: + - .custom_env + volumes: + - grafana_data:/var/lib/grafana + - ../../grafana/:/etc/grafana/provisioning/ + - ../../grafana:/mnt/grafana + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} + #- GF_INSTALL_PLUGINS=${GRAFANA_INSTALL_PLUGINS} + - GF_PATHS_PROVISIONING=/etc/grafana/provisioning + - GF_PATHS_DATA=/var/lib/grafana + - METRICS_IP=${METRICS_IP} + expose: + - "3000/tcp" + ports: + - "3000:3000/tcp" + networks: + default: + ipv4_address: ${GRAFANA_IP} +networks: + default: + name: docker_open5gs_default + ipam: + config: + - subnet: ${TEST_NETWORK} +volumes: + grafana_data: + name: grafana_data + mongodbdata: + name: docker_open5gs_mongodbdata + dbdata: + name: docker_open5gs_dbdata diff --git a/custom_deployments/open5gs_hss_cx/4g-volte-opensips-ims-deploy.yaml b/custom_deployments/open5gs_hss_cx/4g-volte-opensips-ims-deploy.yaml new file mode 100644 index 0000000..3058f82 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/4g-volte-opensips-ims-deploy.yaml @@ -0,0 +1,462 @@ +services: + mongo: + image: mongo:6.0 + container_name: mongo + command: --bind_ip 0.0.0.0 + env_file: + - .custom_env + volumes: + - mongodbdata:/data/db + - mongodbdata:/data/configdb + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "27017/udp" + - "27017/tcp" + networks: + default: + ipv4_address: ${MONGO_IP} + webui: + image: docker_open5gs + container_name: webui + depends_on: + - mongo + env_file: + - .custom_env + environment: + - COMPONENT_NAME=webui + volumes: + - ../../webui:/mnt/webui + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9999/tcp" + ports: + - "9999:9999/tcp" + networks: + default: + ipv4_address: ${WEBUI_IP} + hss: + image: docker_open5gs + container_name: hss + env_file: + - .custom_env + environment: + - COMPONENT_NAME=hss + volumes: + - ./hss:/mnt/hss + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + depends_on: + - mongo + expose: + - "${HSS_BIND_PORT}/tcp" + - "${HSS_BIND_PORT}/sctp" + - "5868/tcp" + - "5868/sctp" + networks: + default: + ipv4_address: ${HSS_IP} + sgwc: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwc + env_file: + - .custom_env + environment: + - COMPONENT_NAME=sgwc + volumes: + - ../../sgwc:/mnt/sgwc + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2123/udp" + - "8805/udp" + networks: + default: + ipv4_address: ${SGWC_IP} + sgwu: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwu + env_file: + - .custom_env + environment: + - COMPONENT_NAME=sgwu + volumes: + - ../../sgwu:/mnt/sgwu + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "8805/udp" + - "2152/udp" + # ports: + # - "2152:2152/udp" + networks: + default: + ipv4_address: ${SGWU_IP} + smf: + image: docker_open5gs + container_name: smf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=smf + - DEPLOY_MODE=4G + volumes: + - ../../smf:/mnt/smf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "8805/udp" + - "2123/udp" + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${SMF_IP} + upf: + image: docker_open5gs + depends_on: + - smf + container_name: upf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=upf + volumes: + - ../../upf:/mnt/upf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2152/udp" + - "8805/udp" + - "9091/tcp" + cap_add: + - NET_ADMIN + privileged: true + sysctls: + - net.ipv4.ip_forward=1 + networks: + default: + ipv4_address: ${UPF_IP} + mme: + image: docker_open5gs + depends_on: + - hss + - sgwc + - sgwu + - smf + - upf + - osmomsc + container_name: mme + env_file: + - .custom_env + environment: + - COMPONENT_NAME=mme + volumes: + - ./mme:/mnt/mme + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "36412/sctp" + - "2123/udp" + - "9091/tcp" + # ports: + # - "36412:36412/sctp" + networks: + default: + ipv4_address: ${MME_IP} + pcrf: + image: docker_open5gs + container_name: pcrf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=pcrf + depends_on: + - mongo + volumes: + - ../../pcrf:/mnt/pcrf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "${PCRF_BIND_PORT}/tcp" + - "${PCRF_BIND_PORT}/sctp" + - "5868/tcp" + - "5868/sctp" + networks: + default: + ipv4_address: ${PCRF_IP} + dns: + build: ./dns + image: docker_dns + container_name: dns + env_file: + - .custom_env + volumes: + - ./dns:/mnt/dns + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "53/udp" + networks: + default: + ipv4_address: ${DNS_IP} + rtpengine: + build: ../../rtpengine + image: docker_rtpengine + container_name: rtpengine + privileged: true + env_file: + - .custom_env + volumes: + - ../../rtpengine:/mnt/rtpengine + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + cap_add: + - NET_ADMIN + environment: + - TABLE=0 + - INTERFACE=${RTPENGINE_IP} + - LISTEN_NG=${RTPENGINE_IP}:2223 + - PIDFILE=/run/ngcp-rtpengine-daemon.pid + - PORT_MAX=50000 + - PORT_MIN=49000 + - NO_FALLBACK=no + - TOS=184 + expose: + - "2223/udp" + - "49000-50000/udp" + networks: + default: + ipv4_address: ${RTPENGINE_IP} + mysql: + build: ../../mysql + image: docker_mysql + container_name: mysql + env_file: + - .custom_env + volumes: + - dbdata:/var/lib/mysql + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3306/tcp" + networks: + default: + ipv4_address: ${MYSQL_IP} + icscf: + image: docker_opensips + container_name: icscf + dns: ${DNS_IP} + volumes: + - ./opensips_ims_icscf:/mnt/icscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=icscf + depends_on: + - dns + - mysql + - hss + expose: + - "${ICSCF_BIND_PORT}/tcp" + - "${ICSCF_BIND_PORT}/sctp" + - "4060/udp" + - "4060/tcp" + networks: + default: + ipv4_address: ${ICSCF_IP} + scscf: + image: docker_opensips + container_name: scscf + dns: ${DNS_IP} + volumes: + - ./opensips_ims_scscf:/mnt/scscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=scscf + depends_on: + - dns + - mysql + - hss + expose: + - "${SCSCF_BIND_PORT}/tcp" + - "${SCSCF_BIND_PORT}/sctp" + - "6060/udp" + - "6060/tcp" + networks: + default: + ipv4_address: ${SCSCF_IP} + pcscf: + image: docker_opensips + container_name: pcscf + dns: ${DNS_IP} + privileged: true + cap_add: + - NET_ADMIN + volumes: + - ../../opensips_ims_pcscf:/mnt/pcscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=pcscf + - DEPLOY_MODE=4G + depends_on: + - dns + - mysql + - rtpengine + - icscf + - scscf + expose: + - "${PCSCF_BIND_PORT}/tcp" + - "${PCSCF_BIND_PORT}/sctp" + - "5060/tcp" + - "5060/udp" + - "5100-5120/tcp" + - "5100-5120/udp" + - "6100-6120/tcp" + - "6100-6120/udp" + networks: + default: + ipv4_address: ${PCSCF_IP} + smsc: + image: docker_kamailio + container_name: smsc + dns: ${DNS_IP} + volumes: + - ../../smsc:/mnt/smsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=smsc + depends_on: + - dns + - mysql + expose: + - "7090/udp" + - "7090/tcp" + networks: + default: + ipv4_address: ${SMSC_IP} + osmomsc: + build: ../../osmomsc + image: docker_osmomsc + container_name: osmomsc + volumes: + - ../../osmomsc:/mnt/osmomsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=osmomsc + depends_on: + - osmohlr + expose: + - "29118/sctp" + - "2775/tcp" + networks: + default: + ipv4_address: ${OSMOMSC_IP} + osmohlr: + build: ../../osmohlr + image: docker_osmohlr + container_name: osmohlr + volumes: + - ../../osmohlr:/mnt/osmohlr + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=osmohlr + expose: + - "4222/tcp" + networks: + default: + ipv4_address: ${OSMOHLR_IP} + metrics: + build: ../../metrics + image: docker_metrics + container_name: metrics + env_file: + - .custom_env + volumes: + - ../../metrics:/mnt/metrics + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9090/tcp" + ports: + - "9090:9090/tcp" + networks: + default: + ipv4_address: ${METRICS_IP} + grafana: + image: grafana/grafana:11.3.0 + container_name: grafana + env_file: + - .custom_env + volumes: + - grafana_data:/var/lib/grafana + - ../../grafana/:/etc/grafana/provisioning/ + - ../../grafana:/mnt/grafana + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} + #- GF_INSTALL_PLUGINS=${GRAFANA_INSTALL_PLUGINS} + - GF_PATHS_PROVISIONING=/etc/grafana/provisioning + - GF_PATHS_DATA=/var/lib/grafana + - METRICS_IP=${METRICS_IP} + expose: + - "3000/tcp" + ports: + - "3000:3000/tcp" + networks: + default: + ipv4_address: ${GRAFANA_IP} +networks: + default: + name: docker_open5gs_default + ipam: + config: + - subnet: ${TEST_NETWORK} +volumes: + grafana_data: + name: grafana_data + mongodbdata: + name: docker_open5gs_mongodbdata + dbdata: + name: docker_open5gs_dbdata diff --git a/custom_deployments/open5gs_hss_cx/README.md b/custom_deployments/open5gs_hss_cx/README.md new file mode 100644 index 0000000..a03529e --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/README.md @@ -0,0 +1,37 @@ +## Deployment description + +This custom deployment showcases using of open5gs HSS for Cx interface (towards ICSCF/SCSCF) rather than using pyHSS. + +## Limitation + +In order to change the iFCs or any other IMS service related provisioning information one need to modify the code and re-compile open5gs i.e. no way to configure them via GUI as we have with pyHSS. + +## Additional steps + +Most of the steps to be followed are similar to the steps mentioned in the [README in the root folder](../../README.md). However, additional steps mentioned below must be taken into account while deploying this custom deployment scenario. + +### Loading environmental variables for custom deployment + +**Warning** +For custom deployments, you must modify/use only the [**.custom_env**](.custom_env) file rather than the [**.env** in the root folder](../../.env). + +``` +set -a +source .custom_env +set +a +``` + +### Scenario deployment + +Deploy the 4G EPC + IMS. + +``` +cd custom_deployments/open5gs_hss_cx +docker compose -f 4g-volte-deploy.yaml up +``` + +Deploy srsRAN eNB using SDR (OTA) + +``` +docker compose -f srsenb.yaml up -d && docker container attach srsenb +``` diff --git a/custom_deployments/open5gs_hss_cx/dns/Dockerfile b/custom_deployments/open5gs_hss_cx/dns/Dockerfile new file mode 100644 index 0000000..f6354f0 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/dns/Dockerfile @@ -0,0 +1,37 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM ubuntu:focal + +ENV DEBIAN_FRONTEND=noninteractive + +# Install updates and dependencies +RUN apt-get update && \ + apt-get -y install tcpdump screen tmux ntp ntpdate iproute2 net-tools \ + iputils-ping bind9 + +CMD /mnt/dns/dns_init.sh && \ + /usr/sbin/named -c /etc/bind/named.conf -g -u bind diff --git a/custom_deployments/open5gs_hss_cx/dns/dns_init.sh b/custom_deployments/open5gs_hss_cx/dns/dns_init.sh new file mode 100755 index 0000000..e63695a --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/dns/dns_init.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +cp /mnt/dns/epc_zone /etc/bind +cp /mnt/dns/ims_zone /etc/bind +cp /mnt/dns/pub_3gpp_zone /etc/bind +cp /mnt/dns/e164.arpa /etc/bind +cp /mnt/dns/named.conf /etc/bind + +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" +[ ${#MNC} == 3 ] && PUB_3GPP_DOMAIN="mnc${MNC}.mcc${MCC}.pub.3gppnetwork.org" || PUB_3GPP_DOMAIN="mnc0${MNC}.mcc${MCC}.pub.3gppnetwork.org" + +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/bind/epc_zone +sed -i 's|DNS_IP|'$DNS_IP'|g' /etc/bind/epc_zone +[ -z "$PCRF_PUB_IP" ] && sed -i 's|PCRF_IP|'$PCRF_IP'|g' /etc/bind/epc_zone || sed -i 's|PCRF_IP|'$PCRF_PUB_IP'|g' /etc/bind/epc_zone +[ -z "$HSS_PUB_IP" ] && sed -i 's|HSS_IP|'$HSS_IP'|g' /etc/bind/epc_zone || sed -i 's|HSS_IP|'$HSS_PUB_IP'|g' /etc/bind/epc_zone + +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/bind/ims_zone +sed -i 's|DNS_IP|'$DNS_IP'|g' /etc/bind/ims_zone +sed -i 's|PCSCF_IP|'$PCSCF_IP'|g' /etc/bind/ims_zone +sed -i 's|ICSCF_IP|'$ICSCF_IP'|g' /etc/bind/ims_zone +sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' /etc/bind/ims_zone +sed -i 's|SMSC_IP|'$SMSC_IP'|g' /etc/bind/ims_zone + +sed -i 's|PUB_3GPP_DOMAIN|'$PUB_3GPP_DOMAIN'|g' /etc/bind/pub_3gpp_zone +sed -i 's|DNS_IP|'$DNS_IP'|g' /etc/bind/pub_3gpp_zone +sed -i 's|ENTITLEMENT_SERVER_IP|'$ENTITLEMENT_SERVER_IP'|g' /etc/bind/pub_3gpp_zone + +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/bind/e164.arpa +sed -i 's|DNS_IP|'$DNS_IP'|g' /etc/bind/e164.arpa + +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/bind/named.conf +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/bind/named.conf +sed -i 's|PUB_3GPP_DOMAIN|'$PUB_3GPP_DOMAIN'|g' /etc/bind/named.conf + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/open5gs_hss_cx/dns/e164.arpa b/custom_deployments/open5gs_hss_cx/dns/e164.arpa new file mode 100644 index 0000000..192d01a --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/dns/e164.arpa @@ -0,0 +1,14 @@ +$TTL 1h +@ IN SOA ns.e164.arpa. root.e164.arpa. ( + 2009010918 ;serial + 3600 ;refresh + 3600 ;retry + 3600 ;expire + 3600 ;minimum TTL +) +@ IN NS e164.arpa. +@ IN A DNS_IP + +; Wildcard to match any tel:+xxxx and change to sip:xxxx@IMS_DOMAIN +* IN NAPTR 10 100 "u" "E2U+sip" "!(^.*$)!sip:\\1@IMS_DOMAIN!" . +* IN NAPTR 20 100 "u" "E2U+sip" "!(^.*$)!sip:+\\1@IMS_DOMAIN!" . diff --git a/custom_deployments/open5gs_hss_cx/dns/epc_zone b/custom_deployments/open5gs_hss_cx/dns/epc_zone new file mode 100644 index 0000000..5089065 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/dns/epc_zone @@ -0,0 +1,15 @@ +$ORIGIN EPC_DOMAIN. +$TTL 1W +@ 1D IN SOA localhost. root.localhost. ( + 1 ; serial + 3H ; refresh + 15M ; retry + 1W ; expiry + 1D ) ; minimum + + 1D IN NS epcns +epcns 1D IN A DNS_IP + +pcrf 1D IN A PCRF_IP + +hss 1D IN A HSS_IP diff --git a/custom_deployments/open5gs_hss_cx/dns/ims_zone b/custom_deployments/open5gs_hss_cx/dns/ims_zone new file mode 100644 index 0000000..1373c02 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/dns/ims_zone @@ -0,0 +1,27 @@ +$ORIGIN IMS_DOMAIN. +$TTL 1W +@ 1D IN SOA localhost. root.localhost. ( + 1 ; serial + 3H ; refresh + 15M ; retry + 1W ; expiry + 1D ) ; minimum + + 1D IN NS ns +ns 1D IN A DNS_IP + +pcscf 1D IN A PCSCF_IP +_sip._udp.pcscf 1D SRV 0 0 5060 pcscf +_sip._tcp.pcscf 1D SRV 0 0 5060 pcscf + +icscf 1D IN A ICSCF_IP +_sip._udp 1D SRV 0 0 4060 icscf +_sip._tcp 1D SRV 0 0 4060 icscf + +scscf 1D IN A SCSCF_IP +_sip._udp.scscf 1D SRV 0 0 6060 scscf +_sip._tcp.scscf 1D SRV 0 0 6060 scscf + +smsc 1D IN A SMSC_IP +_sip._udp.smsc 1D SRV 0 0 7090 smsc +_sip._tcp.smsc 1D SRV 0 0 7090 smsc diff --git a/custom_deployments/open5gs_hss_cx/dns/named.conf b/custom_deployments/open5gs_hss_cx/dns/named.conf new file mode 100644 index 0000000..a6ed6ab --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/dns/named.conf @@ -0,0 +1,53 @@ +options { + directory "/var/cache/bind"; + + // If there is a firewall between you and nameservers you want + // to talk to, you may need to fix the firewall to allow multiple + // ports to talk. See http://www.kb.cert.org/vuls/id/800113 + + // If your ISP provided one or more IP addresses for stable + // nameservers, you probably want to use them as forwarders. + // Uncomment the following block, and insert the addresses replacing + // the all-0's placeholder. + + forwarders { + 8.8.8.8; + }; + + //======================================================================== + // If BIND logs error messages about the root key being expired, + // you will need to update your keys. See https://www.isc.org/bind-keys + //======================================================================== + dnssec-validation no; + allow-query { any; }; + + auth-nxdomain no; # conform to RFC1035 + listen-on-v6 { any; }; +}; + +// +// Do any local configuration here +// + +// Consider adding the 1918 zones here, if they are not used in your +// organization +//include "/etc/bind/zones.rfc1918"; +zone "IMS_DOMAIN" { + type master; + file "/etc/bind/ims_zone"; +}; + +zone "EPC_DOMAIN" { + type master; + file "/etc/bind/epc_zone"; +}; + +zone "PUB_3GPP_DOMAIN" { + type master; + file "/etc/bind/pub_3gpp_zone"; +}; + +zone "e164.arpa" { + type master; + file "/etc/bind/e164.arpa"; +}; diff --git a/custom_deployments/open5gs_hss_cx/dns/pub_3gpp_zone b/custom_deployments/open5gs_hss_cx/dns/pub_3gpp_zone new file mode 100644 index 0000000..e7b27bc --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/dns/pub_3gpp_zone @@ -0,0 +1,13 @@ +$ORIGIN PUB_3GPP_DOMAIN. +$TTL 1W +@ 1D IN SOA localhost. root.localhost. ( + 1 ; serial + 3H ; refresh + 15M ; retry + 1W ; expiry + 1D ) ; minimum + + 1D IN NS pubns +pubns 1D IN A DNS_IP + +aes 1D IN A ENTITLEMENT_SERVER_IP diff --git a/custom_deployments/open5gs_hss_cx/hss/hss.conf b/custom_deployments/open5gs_hss_cx/hss/hss.conf new file mode 100644 index 0000000..34c1ea0 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/hss/hss.conf @@ -0,0 +1,267 @@ +# This is a sample configuration file for freeDiameter daemon. + +# Most of the options can be omitted, as they default to reasonable values. +# Only TLS-related options must be configured properly in usual setups. + +# It is possible to use "include" keyword to import additional files +# e.g.: include "/etc/freeDiameter.d/*.conf" +# This is exactly equivalent as copy & paste the content of the included file(s) +# where the "include" keyword is found. + + +############################################################## +## Peer identity and realm + +# The Diameter Identity of this daemon. +# This must be a valid FQDN that resolves to the local host. +# Default: hostname's FQDN +#Identity = "aaa.koganei.freediameter.net"; +Identity = "hss.EPC_DOMAIN"; + +# The Diameter Realm of this daemon. +# Default: the domain part of Identity (after the first dot). +#Realm = "koganei.freediameter.net"; +Realm = "EPC_DOMAIN"; + +############################################################## +## Transport protocol configuration + +# The port this peer is listening on for incoming connections (TCP and SCTP). +# Default: 3868. Use 0 to disable. +#Port = 3868; +Port = HSS_BIND_PORT; + +# The port this peer is listening on for incoming TLS-protected connections (TCP and SCTP). +# See TLS_old_method for more information about TLS flavours. +# Note: we use TLS/SCTP instead of DTLS/SCTP at the moment. This will change in future version of freeDiameter. +# Default: 5868. Use 0 to disable. +#SecPort = 5868; + +# Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA exchange is completed +# on the unsecure connection. The alternative is RFC6733 mechanism, where TLS protects also the +# CER/CEA exchange on a dedicated secure port. +# This parameter only affects outgoing connections. +# The setting can be also defined per-peer (see Peers configuration section). +# Default: use RFC6733 method with separate port for TLS. +#TLS_old_method; + +# Disable use of TCP protocol (only listen and connect over SCTP) +# Default : TCP enabled +#No_TCP; + +# Disable use of SCTP protocol (only listen and connect over TCP) +# Default : SCTP enabled +#No_SCTP; +# This option is ignored if freeDiameter is compiled with DISABLE_SCTP option. + +# Prefer TCP instead of SCTP for establishing new connections. +# This setting may be overwritten per peer in peer configuration blocs. +# Default : SCTP is attempted first. +#Prefer_TCP; + +# Default number of streams per SCTP associations. +# This setting may be overwritten per peer basis. +# Default : 30 streams +#SCTP_streams = 30; + +############################################################## +## Endpoint configuration + +# Disable use of IP addresses (only IPv6) +# Default : IP enabled +#No_IP; + +# Disable use of IPv6 addresses (only IP) +# Default : IPv6 enabled +#No_IPv6; + +# Specify local addresses the server must bind to +# Default : listen on all addresses available. +#ListenOn = "202.249.37.5"; +#ListenOn = "2001:200:903:2::202:1"; +#ListenOn = "fe80::21c:5ff:fe98:7d62%eth0"; +ListenOn = "HSS_IP"; + +############################################################## +## Server configuration + +# How many Diameter peers are allowed to be connecting at the same time ? +# This parameter limits the number of incoming connections from the time +# the connection is accepted until the first CER is received. +# Default: 5 unidentified clients in paralel. +#ThreadsPerServer = 5; + +############################################################## +## TLS Configuration + +# TLS is managed by the GNUTLS library in the freeDiameter daemon. +# You may find more information about parameters and special behaviors +# in the relevant documentation. +# http://www.gnu.org/software/gnutls/manual/ + +# Credentials of the local peer +# The X509 certificate and private key file to use for the local peer. +# The files must contain PKCS-1 encoded RSA key, in PEM format. +# (These parameters are passed to gnutls_certificate_set_x509_key_file function) +# Default : NO DEFAULT +#TLS_Cred = "" , ""; +#TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key"; +TLS_Cred = "/open5gs/install/etc/freeDiameter/hss.cert.pem", "/open5gs/install/etc/freeDiameter/hss.key.pem"; + +# Certificate authority / trust anchors +# The file containing the list of trusted Certificate Authorities (PEM list) +# (This parameter is passed to gnutls_certificate_set_x509_trust_file function) +# The directive can appear several times to specify several files. +# Default : GNUTLS default behavior +#TLS_CA = ""; +TLS_CA = "/open5gs/install/etc/freeDiameter/cacert.pem"; + +# Certificate Revocation List file +# The information about revoked certificates. +# The file contains a list of trusted CRLs in PEM format. They should have been verified before. +# (This parameter is passed to gnutls_certificate_set_x509_crl_file function) +# Note: openssl CRL format might have interoperability issue with GNUTLS format. +# Default : GNUTLS default behavior +#TLS_CRL = ""; + +# GNU TLS Priority string +# This string allows to configure the behavior of GNUTLS key exchanges +# algorithms. See gnutls_priority_init function documentation for information. +# You should also refer to the Diameter required TLS support here: +# http://tools.ietf.org/html/rfc6733#section-13.1 +# Default : "NORMAL" +# Example: TLS_Prio = "NONE:+VERS-TLS1.1:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL"; +#TLS_Prio = "NORMAL"; + +# Diffie-Hellman parameters size +# Set the number of bits for generated DH parameters +# Valid value should be 768, 1024, 2048, 3072 or 4096. +# (This parameter is passed to gnutls_dh_params_generate2 function, +# it usually should match RSA key size) +# Default : 1024 +#TLS_DH_Bits = 1024; + +# Alternatively, you can specify a file to load the PKCS#3 encoded +# DH parameters directly from. This accelerates the daemon start +# but is slightly less secure. If this file is provided, the +# TLS_DH_Bits parameters has no effect. +# Default : no default. +#TLS_DH_File = ""; + + +############################################################## +## Timers configuration + +# The Tc timer of this peer. +# It is the delay before a new attempt is made to reconnect a disconnected peer. +# The value is expressed in seconds. The recommended value is 30 seconds. +# Default: 30 +#TcTimer = 30; + +# The Tw timer of this peer. +# It is the delay before a watchdog message is sent, as described in RFC 3539. +# The value is expressed in seconds. The default value is 30 seconds. Value must +# be greater or equal to 6 seconds. See details in the RFC. +# Default: 30 +#TwTimer = 30; + +############################################################## +## Applications configuration + +# Disable the relaying of Diameter messages? +# For messages not handled locally, the default behavior is to forward the +# message to another peer if any is available, according to the routing +# algorithms. In addition the "0xffffff" application is advertised in CER/CEA +# exchanges. +# Default: Relaying is enabled. +NoRelay; + +# Number of server threads that can handle incoming messages at the same time. +# Default: 4 +#AppServThreads = 4; + +# Other applications are configured by loaded extensions. + +############################################################## +## Extensions configuration + +# The freeDiameter framework merely provides support for +# Diameter Base Protocol. The specific application behaviors, +# as well as advanced functions, are provided +# by loadable extensions (plug-ins). +# These extensions may in addition receive the name of a +# configuration file, the format of which is extension-specific. +# +# Format: +#LoadExtension = "/path/to/extension" [ : "/optional/configuration/file" ] ; +# +# Examples: +#LoadExtension = "extensions/sample.fdx"; +#LoadExtension = "extensions/sample.fdx":"conf/sample.conf"; + +# Extensions are named as follow: +# dict_* for extensions that add content to the dictionary definitions. +# dbg_* for extensions useful only to retrieve more information on the framework execution. +# acl_* : Access control list, to control which peers are allowed to connect. +# rt_* : routing extensions that impact how messages are forwarded to other peers. +# app_* : applications, these extensions usually register callbacks to handle specific messages. +# test_* : dummy extensions that are useful only in testing environments. + + +# The dbg_msg_dump.fdx extension allows you to tweak the way freeDiameter displays some +# information about some events. This extension does not actually use a configuration file +# but receives directly a parameter in the string passed to the extension. Here are some examples: +## LoadExtension = "dbg_msg_dumps.fdx" : "0x1111"; # Removes all default hooks, very quiet even in case of errors. +## LoadExtension = "dbg_msg_dumps.fdx" : "0x2222"; # Display all events with few details. +## LoadExtension = "dbg_msg_dumps.fdx" : "0x0080"; # Dump complete information about sent and received messages. +# The four digits respectively control: connections, routing decisions, sent/received messages, errors. +# The values for each digit are: +# 0 - default - keep the default behavior +# 1 - quiet - remove any specific log +# 2 - compact - display only a summary of the information +# 4 - full - display the complete information on a single long line +# 8 - tree - display the complete information in an easier to read format spanning several lines. + +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dbg_msg_dumps.fdx" : "0x8888"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_rfc5777.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_mip6i.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_nasreq.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_nas_mipv6.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_dcca.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_dcca_3gpp.fdx"; + + +############################################################## +## Peers configuration + +# The local server listens for incoming connections. By default, +# all unknown connecting peers are rejected. Extensions can override this behavior (e.g., acl_wl). +# +# In addition to incoming connections, the local peer can +# be configured to establish and maintain connections to some +# Diameter nodes and allow connections from these nodes. +# This is achieved with the ConnectPeer directive described below. +# +# Note that the configured Diameter Identity MUST match +# the information received inside CEA, or the connection will be aborted. +# +# Format: +#ConnectPeer = "diameterid" [ { parameter1; parameter2; ...} ] ; +# Parameters that can be specified in the peer's parameter list: +# No_TCP; No_SCTP; No_IP; No_IPv6; Prefer_TCP; TLS_old_method; +# No_TLS; # assume transparent security instead of TLS. DTLS is not supported yet (will change in future versions). +# Port = 5868; # The port to connect to +# TcTimer = 30; +# TwTimer = 30; +# ConnectTo = "202.249.37.5"; +# ConnectTo = "2001:200:903:2::202:1"; +# TLS_Prio = "NORMAL"; +# Realm = "realm.net"; # Reject the peer if it does not advertise this realm. +# Examples: +#ConnectPeer = "aaa.wide.ad.jp"; +#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; Port=3868; } ; +ConnectPeer = "mme.EPC_DOMAIN" { ConnectTo = "MME_IP"; Port = 3868; No_TLS; }; +ConnectPeer = "icscf.IMS_DOMAIN" { ConnectTo = "ICSCF_IP"; Port = ICSCF_BIND_PORT; No_TLS; }; +ConnectPeer = "scscf.IMS_DOMAIN" { ConnectTo = "SCSCF_IP"; Port = SCSCF_BIND_PORT; No_TLS; }; + +############################################################## diff --git a/custom_deployments/open5gs_hss_cx/hss/hss.yaml b/custom_deployments/open5gs_hss_cx/hss/hss.yaml new file mode 100644 index 0000000..bc1785e --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/hss/hss.yaml @@ -0,0 +1,13 @@ +db_uri: mongodb://MONGO_IP/open5gs + +logger: + file: + path: /open5gs/install/var/log/open5gs/hss.log + +global: + max: + ue: MAX_NUM_UE + +hss: + freeDiameter: /open5gs/install/etc/freeDiameter/hss.conf + sms_over_ims: "sip:smsc.IMS_DOMAIN:7090" diff --git a/custom_deployments/open5gs_hss_cx/hss/hss_init.sh b/custom_deployments/open5gs_hss_cx/hss/hss_init.sh new file mode 100755 index 0000000..af0f54e --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/hss/hss_init.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export DB_URI="mongodb://${MONGO_IP}/open5gs" + +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) + +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +ln -s /usr/bin/mongo /usr/bin/mongosh +sed -i "s|localhost|$MONGO_IP|" /open5gs/misc/db/open5gs-dbctl + +cp /mnt/hss/hss.yaml install/etc/open5gs +cp /mnt/hss/hss.conf install/etc/freeDiameter +cp /mnt/hss/make_certs.sh install/etc/freeDiameter + +sed -i 's|HSS_IP|'$HSS_IP'|g' install/etc/freeDiameter/hss.conf +sed -i 's|MME_IP|'$MME_IP'|g' install/etc/freeDiameter/hss.conf +sed -i 's|ICSCF_IP|'$ICSCF_IP'|g' install/etc/freeDiameter/hss.conf +sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' install/etc/freeDiameter/hss.conf +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' install/etc/freeDiameter/hss.conf +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' install/etc/freeDiameter/hss.conf +sed -i 's|ICSCF_BIND_PORT|'$ICSCF_BIND_PORT'|g' install/etc/freeDiameter/hss.conf +sed -i 's|SCSCF_BIND_PORT|'$SCSCF_BIND_PORT'|g' install/etc/freeDiameter/hss.conf +sed -i 's|HSS_BIND_PORT|'$HSS_BIND_PORT'|g' install/etc/freeDiameter/hss.conf +sed -i 's|LD_LIBRARY_PATH|'$LD_LIBRARY_PATH'|g' install/etc/freeDiameter/hss.conf +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' install/etc/freeDiameter/make_certs.sh +sed -i 's|MONGO_IP|'$MONGO_IP'|g' install/etc/open5gs/hss.yaml +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' install/etc/open5gs/hss.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/hss.yaml + +# Generate TLS certificates +./install/etc/freeDiameter/make_certs.sh install/etc/freeDiameter + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/open5gs_hss_cx/hss/make_certs.sh b/custom_deployments/open5gs_hss_cx/hss/make_certs.sh new file mode 100755 index 0000000..2faa713 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/hss/make_certs.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +if [ 1 -ne $# ] +then + echo You must specify output directory : ./make_certs.sh ./freeDiameter + + exit; +fi + +rm -rf demoCA +mkdir demoCA +echo 01 > demoCA/serial +touch demoCA/index.txt.attr +touch demoCA/index.txt + +# Generate .rnd if it does not exist +openssl rand -out /root/.rnd -hex 256 + +# CA self certificate +openssl req -new -batch -x509 -days 3650 -nodes -newkey rsa:1024 -out $1/cacert.pem -keyout cakey.pem -subj /CN=ca.EPC_DOMAIN/C=KO/ST=Seoul/L=Nowon/O=Open5GS/OU=Tests + +#hss +openssl genrsa -out $1/hss.key.pem 1024 +openssl req -new -batch -out hss.csr.pem -key $1/hss.key.pem -subj /CN=hss.EPC_DOMAIN/C=KO/ST=Seoul/L=Nowon/O=Open5GS/OU=Tests +openssl ca -cert $1/cacert.pem -days 3650 -keyfile cakey.pem -in hss.csr.pem -out $1/hss.cert.pem -outdir . -batch + +rm -f 01.pem 02.pem 03.pem 04.pem +rm -f cakey.pem +rm -f hss.csr.pem diff --git a/custom_deployments/open5gs_hss_cx/icscf/icscf.cfg b/custom_deployments/open5gs_hss_cx/icscf/icscf.cfg new file mode 100644 index 0000000..16dd4ce --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/icscf/icscf.cfg @@ -0,0 +1,57 @@ +# SIP / UDP +listen=udp:ICSCF_IP:4060 +# SIP / TCP +listen=tcp:ICSCF_IP:4060 +# SIP / TCP/TLS +#listen=tls:ICSCF_IP:4061 + +alias=IMS_DOMAIN + +#!define NETWORKNAME "IMS_DOMAIN" +#!define EPC_REALM "EPC_DOMAIN" +#!define HOSTNAME "icscf.IMS_DOMAIN" + +#!subst "/NETWORKNAME/IMS_DOMAIN/" + +#!define ENUM_SUFFIX "e164.arpa." + +# Maximum lifetime of a subscription in seconds (same is advertised to UE) +#!substdef "/UE_SUBSCRIPTION_EXPIRES/SUBSCRIPTION_EXPIRES_ENV/g" + +# SIP-Address of capturing node, if not set, capturing is disabled. +##!define CAPTURE_NODE "sip:127.0.0.1:9060" + +# Connection URL for the database: +#!define DB_URL "mysql://icscf:heslo@MYSQL_IP/icscf" +##!define DB_URL2 "con2=>mysql://icscf:heslo@MYSQL_IP/icscf" + +# Allowed IPs for XML-RPC-Queries +##!define XMLRPC_WHITELIST_1 "127.0.0.1" +##!define XMLRPC_WHITELIST_2 "127.0.0.1" +##!define XMLRPC_WHITELIST_3 "127.0.0.1" + +# *** To run in debug mode: +# - define WITH_DEBUG +# +# *** To enable TLS support execute: +# - adjust CFGDIR/tls.cfg as needed +# - define WITH_TLS +# +# *** To enable XMLRPC support execute: +# - define WITH_XMLRPC +# - adjust route[XMLRPC] for access policy +# +# *** To enable a Homer SIP-Capter-Node: +# - define CAPTURE_NODE with a proper address +# +# *** To forwarding to PSTN for unknown users: +# - define PEERING +# +# Enabled Features for this host: +##!define WITH_DEBUG +##!define WITH_DEBUG_TRACE +#!define WITH_TCP +##!define WITH_TLS +#!define WITH_XMLRPC +##!define PEERING +##!define FALLBACK_AUTH diff --git a/custom_deployments/open5gs_hss_cx/icscf/icscf.xml b/custom_deployments/open5gs_hss_cx/icscf/icscf.xml new file mode 100644 index 0000000..e2cad2c --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/icscf/icscf.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + diff --git a/custom_deployments/open5gs_hss_cx/icscf/icscf_init.sh b/custom_deployments/open5gs_hss_cx/icscf/icscf_init.sh new file mode 100755 index 0000000..b443c42 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/icscf/icscf_init.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +mkdir -p /etc/kamailio_icscf +cp /mnt/icscf/icscf.cfg /etc/kamailio_icscf +cp /mnt/icscf/icscf.xml /etc/kamailio_icscf +cp /mnt/icscf/kamailio_icscf.cfg /etc/kamailio_icscf + +while ! mysqladmin ping -h ${MYSQL_IP} --silent; do + sleep 5; +done + +# Sleep until permissions are set +sleep 10; + +# Create ICSCF database, populate tables and grant privileges +if [[ -z "`mysql -u root -h ${MYSQL_IP} -qfsBe "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='icscf'" 2>&1`" ]]; +then + mysql -u root -h ${MYSQL_IP} -e "create database icscf;" + mysql -u root -h ${MYSQL_IP} icscf < /usr/local/src/kamailio/misc/examples/ims/icscf/icscf.sql + + ICSCF_USER_EXISTS=`mysql -u root -h ${MYSQL_IP} -s -N -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE User = 'icscf' AND Host = '%')"` + if [[ "$ICSCF_USER_EXISTS" == 0 ]] + then + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'icscf'@'%' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'provisioning'@'%' IDENTIFIED WITH mysql_native_password BY 'provi'"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'icscf'@'$ICSCF_IP' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'provisioning'@'$ICSCF_IP' IDENTIFIED WITH mysql_native_password BY 'provi'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON icscf.* TO 'icscf'@'%'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON icscf.* TO 'icscf'@'$ICSCF_IP'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON icscf.* TO 'provisioning'@'%'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON icscf.* TO 'provisioning'@'$ICSCF_IP'"; + mysql -u root -h ${MYSQL_IP} -e "FLUSH PRIVILEGES;" + fi +fi + +DOMAIN_PRESENT=`mysql -u root -h ${MYSQL_IP} icscf -s -N -e "SELECT count(*) FROM nds_trusted_domains WHERE trusted_domain='$IMS_DOMAIN';"` +if [[ "$DOMAIN_PRESENT" == 0 ]] +then + mysql -u root -h ${MYSQL_IP} icscf -e "INSERT INTO nds_trusted_domains (trusted_domain) VALUES ('$IMS_DOMAIN');" +fi + +URI_PRESENT=`mysql -u root -h ${MYSQL_IP} icscf -s -N -e "SELECT count(*) FROM s_cscf WHERE s_cscf_uri='sip:scscf.$IMS_DOMAIN:6060';"` +if [[ "$URI_PRESENT" == 0 ]] +then + mysql -u root -h ${MYSQL_IP} icscf -e "INSERT INTO s_cscf (name, s_cscf_uri) VALUES ('First and only S-CSCF', 'sip:scscf.$IMS_DOMAIN:6060');" +fi + +SCSCF_ID=`mysql -u root -h ${MYSQL_IP} icscf -s -N -e "SELECT id FROM s_cscf WHERE s_cscf_uri='sip:scscf.$IMS_DOMAIN:6060' LIMIT 1;"` +CAP_PRESENT=`mysql -u root -h ${MYSQL_IP} icscf -s -N -e "SELECT count(*) FROM s_cscf_capabilities WHERE id_s_cscf='$SCSCF_ID';"` +if [[ "$CAP_PRESENT" == 0 ]] +then + mysql -u root -h ${MYSQL_IP} icscf -e "INSERT INTO s_cscf_capabilities (id_s_cscf, capability) VALUES ('$SCSCF_ID', 0),('$SCSCF_ID', 1);" +fi + +SUBSCRIPTION_EXPIRES_ENV=3600 + +sed -i 's|ICSCF_IP|'$ICSCF_IP'|g' /etc/kamailio_icscf/icscf.cfg +sed -i 's|SUBSCRIPTION_EXPIRES_ENV|'$SUBSCRIPTION_EXPIRES_ENV'|g' /etc/kamailio_icscf/icscf.cfg +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/kamailio_icscf/icscf.cfg +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/kamailio_icscf/icscf.cfg +sed -i 's|MYSQL_IP|'$MYSQL_IP'|g' /etc/kamailio_icscf/icscf.cfg + +sed -i 's|ICSCF_IP|'$ICSCF_IP'|g' /etc/kamailio_icscf/icscf.xml +sed -i 's|SUBSCRIPTION_EXPIRES_ENV|'$SUBSCRIPTION_EXPIRES_ENV'|g' /etc/kamailio_icscf/icscf.xml +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/kamailio_icscf/icscf.xml +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/kamailio_icscf/icscf.xml +sed -i 's|HSS_BIND_PORT|'$HSS_BIND_PORT'|g' /etc/kamailio_icscf/icscf.xml +sed -i 's|ICSCF_BIND_PORT|'$ICSCF_BIND_PORT'|g' /etc/kamailio_icscf/icscf.xml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/open5gs_hss_cx/icscf/kamailio_icscf.cfg b/custom_deployments/open5gs_hss_cx/icscf/kamailio_icscf.cfg new file mode 100644 index 0000000..87960f4 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/icscf/kamailio_icscf.cfg @@ -0,0 +1,643 @@ +#!KAMAILIO +# +# This config file implements the basic I-CSCF functionality +# - web: http://www.kamailio.org +# - git: http://sip-router.org +# +# Refer to the Core CookBook at http://www.kamailio.org/dokuwiki/doku.php +# for an explanation of possible statements, functions and parameters. +# +# Direct your questions about this file to: . +# +# For more information about the various parameters, functions and statements +# try http://sip-router.org/wiki/ . +# + +system.shutdownmode = 0 desc "System shutdown mode" +system.service = "Interrogating-CSCF" desc "Function of this server" + +include_file "icscf.cfg" + +####### Defined Values ######### +# *** Value defines - IDs used later in config + +# - flags +# FLT_ - per transaction (message) flags +# FLB_ - per branch flags + +#!define FLT_CAPTURE 1 + +#!ifdef WITH_XMLRPC +listen=tcp:127.0.0.1:4060 +#!endif + +####### Global Parameters ######### +debug=2 +log_stderror=no +sip_warning=no + +user_agent_header="User-Agent: Kamailio I-CSCF" +server_header="Server: Kamailio I-CSCF" +log_name="icscf" +log_prefix_mode=1 +log_prefix="{$mt $hdr(CSeq) $ci $cfg(route)} " + +/* comment the next line to enable the auto discovery of local aliases + based on reverse DNS on IPs (default on) */ +auto_aliases=no + +# Do SRV-Loadbalancing: +dns_srv_lb=on +# Always: Also try IPv6: +dns_try_ipv6=on +# Query NAPTR-Records as well: +dns_try_naptr=no + +#!ifdef WITH_XMLRPC +#!ifndef WITH_TCP +#!define WITH_TCP +#!endif +#!ifndef TCP_PROCESSES +# Number of TCP Processes +#!define TCP_PROCESSES 3 +#!endif +#!endif + +#!ifdef WITH_TCP +# life time of TCP connection when there is no traffic +# - a bit higher than registration expires to cope with UA behind NAT +tcp_connection_lifetime=UE_SUBSCRIPTION_EXPIRES +#!ifdef TCP_PROCESSES +tcp_children=TCP_PROCESSES +#!endif +#!else +disable_tcp=yes +#!endif + +check_via=no # (cmd. line: -v) +dns=no # (cmd. line: -r) +rev_dns=no # (cmd. line: -R) + +children=4 + +# ------------------ module loading ---------------------------------- +mpath="/usr/lib64/kamailio/modules_k/:/usr/lib64/kamailio/modules/:/usr/lib/kamailio/modules_k/:/usr/lib/kamailio/modules/:/usr/lib/x86_64-linux-gnu/kamailio/modules/:/usr/local/lib64/kamailio/modules" +# (we try both the lib64 and the lib directory) +loadmodule "tm" +loadmodule "sl" +loadmodule "rr" +loadmodule "pv" +loadmodule "textops" +loadmodule "maxfwd" +loadmodule "sanity" +loadmodule "siputils" +loadmodule "kex" +loadmodule "tmx" +loadmodule "pike" +loadmodule "corex" + +# Control interfaces: +loadmodule "ctl" +loadmodule "cfg_rpc" +#!ifdef WITH_XMLRPC +loadmodule "xmlrpc" +#!endif + +# Load the according DB-Module: +loadmodule "db_mysql" +#!ifdef DB_URL2 +loadmodule "db_cluster" +#!endif + +loadmodule "cdp.so" +loadmodule "cdp_avp.so" +loadmodule "xlog.so" + +loadmodule "ims_icscf.so" + +#!ifdef CAPTURE_NODE +loadmodule "siptrace.so" +#!endif + +#!ifdef WITH_DEBUG +loadmodule "debugger.so" +#!endif + +#!ifdef WITH_TLS +loadmodule "tls.so" +#!endif + +#!ifdef PEERING +loadmodule "enum" +loadmodule "dispatcher" +#!endif + +# ----------------- setting module-specific parameters --------------- +#!ifdef DB_URL2 +# ----- db_cluster params ----- +modparam("db_cluster", "connection", DB_URL) +modparam("db_cluster", "connection", DB_URL2) +modparam("db_cluster", "cluster", "cluster1=>con1=2s2s;con2=1s1s") +#!endif + +loadmodule "jsonrpcs.so" +# ----- jsonrpcs params ----- +modparam("jsonrpcs", "pretty_format", 1) +/* set the path to RPC fifo control file */ +modparam("jsonrpcs", "fifo_name", "/var/run/kamailio/kamailio_rpc.fifo") +/* set the path to RPC unix socket control file */ +modparam("jsonrpcs", "dgram_socket", "/var/run/kamailio/kamailio_rpc.sock") + +# -- rr params -- +# add value to ;lr param to make some broken UAs happy +modparam("rr", "enable_full_lr", 1) + +# -- cdp params -- +modparam("cdp","config_file","/etc/kamailio_icscf/icscf.xml") + +# ----- icscf params ----- +# Comment the following line to enable realm routing +#!ifdef CXDX_FORCED_PEER +modparam("ims_icscf", "cxdx_forced_peer", CXDX_FORCED_PEER) +#!endif +modparam("ims_icscf","cxdx_dest_realm", EPC_REALM) + +# DB-URL, where information about S-CSCF-Server can be found: +#!ifdef DB_URL2 +modparam("ims_icscf", "db_url", "cluster://cluster1") +#!else +modparam("ims_icscf", "db_url", DB_URL) +#!endif + +#!ifdef PEERING +# Route which is executed, in case HSS returned "User-Unknown" on LIR request +modparam("ims_icscf","route_lir_user_unknown", "lir_term_user_unknown") +#!endif +#!ifdef FALLBACK_AUTH +# Route which is executed, in case HSS returned "User-Unknown" on UAR request +modparam("ims_icscf","route_uar_user_unknown", "uar_term_user_unknown") +#!endif + +#!ifdef WITH_TLS +# ----- tls params ----- +modparam("tls", "config", "/etc/kamailio_icscf/tls.cfg") +#!endif + +#!ifdef WITH_XMLRPC +# ----- xmlrpc params ----- +modparam("xmlrpc", "route", "XMLRPC"); +modparam("xmlrpc", "url_match", "^/RPC") +#!endif + +# ----- ctl params ----- +modparam("ctl", "binrpc", "unix:/var/run/kamailio/kamailio_ctl") + +#!ifdef WITH_DEBUG +# ----- debugger params ----- +modparam("debugger", "mod_hash_size", 5) +modparam("debugger", "mod_level_mode", 1) +modparam("debugger", "mod_level", "xlog=3") +modparam("debugger", "mod_level", "cdp=3") +modparam("debugger", "mod_level", "ims_icscf=3") +#!ifdef WITH_DEBUG_TRACE +modparam("debugger", "cfgtrace", 1) +#!endif +#!endif + +#!ifdef CAPTURE_NODE +# Destination, where to send the traffic +modparam("siptrace", "duplicate_uri", CAPTURE_NODE) +# Trace all traffic +modparam("siptrace", "trace_on", 1) +modparam("siptrace", "trace_to_database", 0) +modparam("siptrace", "trace_flag", FLT_CAPTURE) +modparam("siptrace", "hep_mode_on", 1) +#!endif + +#!ifdef PEERING +# ----- enum params ----- +modparam("enum", "domain_suffix", ENUM_SUFFIX) +#!endif + +# ----- tm params ----- +# auto-discard branches from previous serial forking leg +modparam("tm", "failure_reply_mode", 3) +# default retransmission timeout: 10sec +modparam("tm", "fr_timer", 10000) +# default invite retransmission timeout after 1xx: 120sec +modparam("tm", "fr_inv_timer", 120000) +# Don't reply automatically with "100 Trying" +modparam("tm", "auto_inv_100", 0) + +#!ifdef WITH_DEBUG +#loadmodule "debugger.so" +modparam("debugger", "mod_hash_size", 5) +modparam("debugger", "mod_level_mode", 1) +modparam("debugger", "mod_level", "cdp=3") +modparam("debugger", "mod_level", "ims_icscf=3") +#!endif + +# ------------------------- request routing logic ------------------- +# main routing logic + +route{ +#!ifdef WITH_DEBUG + xlog("I-CSCF >>>>>>>>>>>>>>>>>>>> $rm $ru ($fu => $tu ($si:$sp) to $tu, $ci)\n"); +#!endif + +# if !($rU =~ "\+.*") { +# prefix("+"); +# } + + # per request initial checks + route(REQINIT); + + if (is_method("REGISTER")) { + route(register); + } + + if (is_method("NOTIFY") && search("^(Event|o)([ \t]*):([ \t]*)reg")) { + if (!t_relay()) { + sl_reply_error(); + } + exit; + } + + if (is_method("INVITE|SUBSCRIBE|MESSAGE|INFO|PUBLISH|CANCEL")) { + route(initial_request); + } else { + # Shouldn't get here unless missconfigured (add more methods as initial) or + # somebody is routing unknown messages + append_to_reply("Allow: INVITE,SUBSCRIBE,MESSAGE,INFO,PUBLISH,CANCEL\r\n"); + send_reply("406","Initial Request Method not allowed at the I-CSCF"); + break; + } +} + +###################################################################### +# Helper routes (Basic-Checks, NAT-Handling/RTP-Control, XML-RPC) +###################################################################### +# Per SIP request initial checks +route[REQINIT] { + $var(used) = 1 - ($stat(free_size) / $stat(total_size)); + xlog("L_DBG", "Mem: Total $stat(total_size), Free $stat(free_size) [$var(used)% used]\n"); + if ($var(used) > 95) { + send_reply("503", "Server overloaded"); + exit; + } + + + # Trace this message +#!ifdef CAPTURE_NODE + sip_trace(); + setflag(FLT_CAPTURE); +#!endif + if (!mf_process_maxfwd_header("10")) { + sl_send_reply("483","Too Many Hops"); + exit; + } + if(!sanity_check("1511", "7")) { + xlog("Malformed SIP message from $si:$sp\n"); + exit; + } + + # Check for shutdown mode: + if (!has_totag() && ($sel(cfg_get.system.shutdownmode) > 0)) { + send_reply("503", "Server shutting down"); + exit; + } + + # Reply to OPTIONS: + if (is_method("OPTIONS") && (uri==myself)) { + options_reply(); + exit; + } + + # Ignore Re-Transmits: + if (t_lookup_request()) { + exit; + } + + if (is_method("INVITE|REGISTER")) { + send_reply("100", "Trying"); + } +} + +###################################################################### +# XMLRPC routing +###################################################################### +#!ifdef WITH_XMLRPC +route[XMLRPC] { + if ((method=="POST" || method=="GET") +#!ifdef XMLRPC_WHITELIST_1 +&& ((src_ip == XMLRPC_WHITELIST_1) +#!ifdef XMLRPC_WHITELIST_2 + || (src_ip == XMLRPC_WHITELIST_2) +#!endif +#!ifdef XMLRPC_WHITELIST_3 + || (src_ip == XMLRPC_WHITELIST_3) +#!endif +) +#!endif +) { + # close connection only for xmlrpclib user agents (there is a bug in + # xmlrpclib: it waits for EOF before interpreting the response). + if ($hdr(User-Agent) =~ "xmlrpclib") + set_reply_close(); + set_reply_no_connect(); + dispatch_rpc(); + exit; + } + send_reply("403", "Forbidden"); + exit; +} +#!endif + +###################################################################### +# Handling of REGISTER requests +###################################################################### +route[register] +{ + t_set_fr(5000, 5000); + #first check if we have an S-CSCF list + if (I_scscf_select("0")) { + #there is an S-CSCF list - no need to do a UAR + t_on_reply("register_reply"); + t_on_failure("register_failure"); + if (!t_relay()) { + send_reply("500","Error forwarding towards S-CSCF"); + } + } else { + #no S-CSCF list therefore must do UAR + #free this from the failed I_scscf_select call + I_scscf_drop(); + # Do an asynchronous UAR: + #0=REG/DEREG; 1=REG+Capabilities + if (!I_perform_user_authorization_request("REG_UAR_REPLY","0")) { + send_reply("500", "Error in Request"); + } + } + exit; +} + +route[REG_UAR_REPLY] +{ + #xlog("$$avp(s:uaa_return_code) = $avp(s:uaa_return_code)\n"); + #this is async so to know status we have to check the reply avp + switch ($avp(s:uaa_return_code)) { + case 1: #success + if (I_scscf_select("0")) { + t_on_failure("register_failure"); + t_on_reply("register_reply"); + #now relay to appropriate SCSCF + if (!t_relay()) { + t_reply("500", "Error forwarding to SCSCF"); + } + } else {#select failed + I_scscf_drop(); + t_reply("500", "Server error on SCSCF Select (UAR)"); + } + break; + case -1: #failure + xlog("L_ERR", "UAR failure - error response sent from module\n"); + break; + case -2: #error + xlog("L_ERR", "UAR error - sending error response now\n"); + t_reply("500", "UAR failed"); + break; + default: + xlog("L_ERR", "Unknown return code from UAR, value is [$avp(s:uaa_return_code)]\n"); + t_reply("500", "Unknown response code from UAR"); + break; + } +} + + +###################################################################### +# Replies to REGISTER requests, +###################################################################### +onreply_route[register_reply] +{ + xlog("L_DBG", "Enter register reply block"); + if (!t_check_status("(408)|(480)")){ + if (!t_check_status("(401)")){ + xlog("L_DBG", "dropping scscf list on register failure"); + I_scscf_drop(); + } else { + xlog("L_DBG", "This is a 401 - keep scscf list to do optimisation"); + } + } + break; +} + +###################################################################### +# Failed REGISTERs +###################################################################### +failure_route[register_failure] +{ + if (t_branch_timeout() || t_check_status("([5-6][0-9][0-9])")){ + if (I_scscf_select("1")) { + t_on_reply("register_reply"); + t_on_failure("register_failure"); + if (!t_relay()) { + t_reply("500","Error forwarding towards next S-CSCF"); + break; + } + break; + } else { + t_reply("500", "Server error on UAR select next S-CSCF"); + break; + } + } else { + if (!t_check_status("(401)")){ + xlog("L_DBG", "dropping scscf list on register failure"); + I_scscf_drop(); + } else { + xlog("L_DBG", "This is a 401 - keep scscf list to do optimisation"); + } + break; + } +} + +###################################################################### +# Initial requests +###################################################################### +route[initial_request] +{ +# $avp(prefix)="+"; +# $ru= $(ru{s.rm,$avp(prefix)}); + xlog("$$ru => $ru\n"); + I_perform_location_information_request("LIR_REPLY", "0"); +} + +route[LIR_REPLY] { + if ($avp(lia_return_code) == 1) { + if (I_scscf_select("0")) { + xlog("L_DBG", "ru = $ru, du = $du\n"); + t_on_reply("initial_request_reply"); + t_on_failure("initial_request_failure"); + if (!t_relay()) { + t_reply("500","Error forwarding towards S-CSCF"); + break; + } + break; + } else { + xlog("L_DBG", "dropping scscf list on initial request"); + I_scscf_drop(); + t_reply("500", "Server error on LIR select S-CSCF"); + break; + } + } else { + t_reply("500", "Server error on LIR"); + break; + } + break; +} + +###################################################################### +# Replies to initial requests +###################################################################### +onreply_route[initial_request_reply] +{ + xlog("L_DBG", "Enter initial request request block"); + if (!t_check_status("(408)")){ + xlog("L_DBG", "dropping scscf list on initial request reply"); + I_scscf_drop(); + } + break; +} + +###################################################################### +# Failed initial requests +###################################################################### +failure_route[initial_request_failure] +{ + xlog("L_DBG", "Enter initial request failure block"); + if (t_check_status("(408)")){ + xlog("L_DBG", "Got a failure for initial request"); + if (I_scscf_select("1")) { + t_on_reply("initial_request_reply"); + t_on_failure("initial_request_failure"); + if (!t_relay()) { + t_reply("500","Error forwarding towards next S-CSCF"); + break; + } + break; + } else { + t_reply("500", "Server error on LIR select next S-CSCF"); + break; + } + } else { + xlog("L_DBG", "dropping scscf list on initial request failure"); + I_scscf_drop(); + } + break; +} + +#!ifdef PEERING +###################################################################### +# HSS returned "User-Unknown" on LIR request +###################################################################### +route[lir_term_user_unknown] +{ + if (uri =~ "tel:.*") { + # Let's check, if the number can be found in ENUM: + if(!enum_query()) { + # ENUM failed, send it to the PSTN-Gateway: + route(PSTN); + break; + } + + # ENUM resolved to another domain + if ($rd != NETWORKNAME) { + t_on_reply("initial_request_reply"); + t_on_failure("initial_request_failure"); + if (!t_relay()) { + t_reply("500","Error forwarding to external domain"); + exit; + }; + exit; + } else { + t_reply("604","Does not exist anywhere - HSS User Unknown"); + exit; + }; + } else { + # we received a request for our domain (non-tel), but HSS said "User Unknown" + if ($rd != NETWORKNAME) { + t_reply("604","Does not exist anywhere - HSS User Unknown"); + exit; + } else { + # try to forward non-tel request to other domain + t_on_reply("initial_request_reply"); + t_on_failure("initial_request_failure"); + if (!t_relay()) { + t_reply("500","Error forwarding to external domain"); + exit; + }; + exit; + }; + }; +} + +###################################################################### +# Send calls to the PSTN-Gateways: +###################################################################### +route[PSTN] +{ + t_on_failure("PSTN_failure"); + # Relay the request towards the PSTN-Gateway: + if (!ds_select_dst("1", "4")) { + send_reply("503", "Service not available"); + exit; + } + # Relay the request: + if (!t_relay()) { + send_reply("503", "Service not available"); + exit; + }; + exit; +} + +###################################################################### +# manage failure routing cases, perform failover +###################################################################### +failure_route[PSTN_failure] { + # Choose another gateway, in case we + # - get a local generated "408" + # - receive a 5xx or 6xx reply from the proxy. + if (t_branch_timeout() || t_check_status("[5-6]..")) { + if (ds_next_dst()) { + # Do Failover in case problems: + t_on_failure("PSTN_failure"); + # Relay the request: + if (!t_relay()) { + send_reply("503", "Service not available"); + exit; + }; + } else { + # Add a header, to indicate the phone should try again in 30 seconds. + append_hf("Retry-After: 30\r\n"); + send_reply("503", "Service not available"); + } + exit; + } +} +#!endif + +#!ifdef FALLBACK_AUTH +###################################################################### +# HSS returned "User-Unknown" on UAR request, +# try to send it to any S-CSCF for authentication +###################################################################### +route[uar_term_user_unknown] +{ + $rd = "scscf."+NETWORKNAME; + t_on_reply("register_reply"); + t_on_failure("register_failure"); + if (!t_relay()) { + t_reply("500","Error forwarding towards S-CSCF"); + break; + } + break; +} +#!endif diff --git a/custom_deployments/open5gs_hss_cx/mme/make_certs.sh b/custom_deployments/open5gs_hss_cx/mme/make_certs.sh new file mode 100755 index 0000000..c500418 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/mme/make_certs.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +if [ 1 -ne $# ] +then + echo You must specify output directory : ./make_certs.sh ./freeDiameter + + exit; +fi + +rm -rf demoCA +mkdir demoCA +echo 01 > demoCA/serial +touch demoCA/index.txt.attr +touch demoCA/index.txt + +# Generate .rnd if it does not exist +openssl rand -out /root/.rnd -hex 256 + +# CA self certificate +openssl req -new -batch -x509 -days 3650 -nodes -newkey rsa:1024 -out $1/cacert.pem -keyout cakey.pem -subj /CN=ca.EPC_DOMAIN/C=KO/ST=Seoul/L=Nowon/O=Open5GS/OU=Tests + +#mme +openssl genrsa -out $1/mme.key.pem 1024 +openssl req -new -batch -out mme.csr.pem -key $1/mme.key.pem -subj /CN=mme.EPC_DOMAIN/C=KO/ST=Seoul/L=Nowon/O=Open5GS/OU=Tests +openssl ca -cert $1/cacert.pem -days 3650 -keyfile cakey.pem -in mme.csr.pem -out $1/mme.cert.pem -outdir . -batch + +rm -rf demoCA +rm -f 01.pem 02.pem 03.pem 04.pem +rm -f cakey.pem +rm -f mme.csr.pem diff --git a/custom_deployments/open5gs_hss_cx/mme/mme.conf b/custom_deployments/open5gs_hss_cx/mme/mme.conf new file mode 100644 index 0000000..c1d8358 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/mme/mme.conf @@ -0,0 +1,266 @@ +# This is a sample configuration file for freeDiameter daemon. + +# Most of the options can be omitted, as they default to reasonable values. +# Only TLS-related options must be configured properly in usual setups. + +# It is possible to use "include" keyword to import additional files +# e.g.: include "/etc/freeDiameter.d/*.conf" +# This is exactly equivalent as copy & paste the content of the included file(s) +# where the "include" keyword is found. + + +############################################################## +## Peer identity and realm + +# The Diameter Identity of this daemon. +# This must be a valid FQDN that resolves to the local host. +# Default: hostname's FQDN +#Identity = "aaa.koganei.freediameter.net"; +Identity = "mme.EPC_DOMAIN"; + +# The Diameter Realm of this daemon. +# Default: the domain part of Identity (after the first dot). +#Realm = "koganei.freediameter.net"; +Realm = "EPC_DOMAIN"; + +############################################################## +## Transport protocol configuration + +# The port this peer is listening on for incoming connections (TCP and SCTP). +# Default: 3868. Use 0 to disable. +#Port = 3868; + +# The port this peer is listening on for incoming TLS-protected connections (TCP and SCTP). +# See TLS_old_method for more information about TLS flavours. +# Note: we use TLS/SCTP instead of DTLS/SCTP at the moment. This will change in future version of freeDiameter. +# Default: 5868. Use 0 to disable. +#SecPort = 5868; + +# Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA exchange is completed +# on the unsecure connection. The alternative is RFC6733 mechanism, where TLS protects also the +# CER/CEA exchange on a dedicated secure port. +# This parameter only affects outgoing connections. +# The setting can be also defined per-peer (see Peers configuration section). +# Default: use RFC6733 method with separate port for TLS. +#TLS_old_method; + +# Disable use of TCP protocol (only listen and connect over SCTP) +# Default : TCP enabled +#No_TCP; + +# Disable use of SCTP protocol (only listen and connect over TCP) +# Default : SCTP enabled +#No_SCTP; +# This option is ignored if freeDiameter is compiled with DISABLE_SCTP option. + +# Prefer TCP instead of SCTP for establishing new connections. +# This setting may be overwritten per peer in peer configuration blocs. +# Default : SCTP is attempted first. +#Prefer_TCP; + +# Default number of streams per SCTP associations. +# This setting may be overwritten per peer basis. +# Default : 30 streams +#SCTP_streams = 30; + +############################################################## +## Endpoint configuration + +# Disable use of IP addresses (only IPv6) +# Default : IP enabled +#No_IP; + +# Disable use of IPv6 addresses (only IP) +# Default : IPv6 enabled +#No_IPv6; + +# Specify local addresses the server must bind to +# Default : listen on all addresses available. +#ListenOn = "202.249.37.5"; +#ListenOn = "2001:200:903:2::202:1"; +#ListenOn = "fe80::21c:5ff:fe98:7d62%eth0"; +ListenOn = "MME_IP"; + + +############################################################## +## Server configuration + +# How many Diameter peers are allowed to be connecting at the same time ? +# This parameter limits the number of incoming connections from the time +# the connection is accepted until the first CER is received. +# Default: 5 unidentified clients in paralel. +#ThreadsPerServer = 5; + +############################################################## +## TLS Configuration + +# TLS is managed by the GNUTLS library in the freeDiameter daemon. +# You may find more information about parameters and special behaviors +# in the relevant documentation. +# http://www.gnu.org/software/gnutls/manual/ + +# Credentials of the local peer +# The X509 certificate and private key file to use for the local peer. +# The files must contain PKCS-1 encoded RSA key, in PEM format. +# (These parameters are passed to gnutls_certificate_set_x509_key_file function) +# Default : NO DEFAULT +#TLS_Cred = "" , ""; +#TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key"; +TLS_Cred = "/open5gs/install/etc/freeDiameter/mme.cert.pem", "/open5gs/install/etc/freeDiameter/mme.key.pem"; + +# Certificate authority / trust anchors +# The file containing the list of trusted Certificate Authorities (PEM list) +# (This parameter is passed to gnutls_certificate_set_x509_trust_file function) +# The directive can appear several times to specify several files. +# Default : GNUTLS default behavior +#TLS_CA = ""; +TLS_CA = "/open5gs/install/etc/freeDiameter/cacert.pem"; + +# Certificate Revocation List file +# The information about revoked certificates. +# The file contains a list of trusted CRLs in PEM format. They should have been verified before. +# (This parameter is passed to gnutls_certificate_set_x509_crl_file function) +# Note: openssl CRL format might have interoperability issue with GNUTLS format. +# Default : GNUTLS default behavior +#TLS_CRL = ""; + +# GNU TLS Priority string +# This string allows to configure the behavior of GNUTLS key exchanges +# algorithms. See gnutls_priority_init function documentation for information. +# You should also refer to the Diameter required TLS support here: +# http://tools.ietf.org/html/rfc6733#section-13.1 +# Default : "NORMAL" +# Example: TLS_Prio = "NONE:+VERS-TLS1.1:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL"; +#TLS_Prio = "NORMAL"; + +# Diffie-Hellman parameters size +# Set the number of bits for generated DH parameters +# Valid value should be 768, 1024, 2048, 3072 or 4096. +# (This parameter is passed to gnutls_dh_params_generate2 function, +# it usually should match RSA key size) +# Default : 1024 +#TLS_DH_Bits = 1024; + +# Alternatively, you can specify a file to load the PKCS#3 encoded +# DH parameters directly from. This accelerates the daemon start +# but is slightly less secure. If this file is provided, the +# TLS_DH_Bits parameters has no effect. +# Default : no default. +#TLS_DH_File = ""; + + +############################################################## +## Timers configuration + +# The Tc timer of this peer. +# It is the delay before a new attempt is made to reconnect a disconnected peer. +# The value is expressed in seconds. The recommended value is 30 seconds. +# Default: 30 +#TcTimer = 30; + +# The Tw timer of this peer. +# It is the delay before a watchdog message is sent, as described in RFC 3539. +# The value is expressed in seconds. The default value is 30 seconds. Value must +# be greater or equal to 6 seconds. See details in the RFC. +# Default: 30 +#TwTimer = 30; + +############################################################## +## Applications configuration + +# Disable the relaying of Diameter messages? +# For messages not handled locally, the default behavior is to forward the +# message to another peer if any is available, according to the routing +# algorithms. In addition the "0xffffff" application is advertised in CER/CEA +# exchanges. +# Default: Relaying is enabled. +NoRelay; + +# Number of server threads that can handle incoming messages at the same time. +# Default: 4 +#AppServThreads = 4; + +# Other applications are configured by loaded extensions. + +############################################################## +## Extensions configuration + +# The freeDiameter framework merely provides support for +# Diameter Base Protocol. The specific application behaviors, +# as well as advanced functions, are provided +# by loadable extensions (plug-ins). +# These extensions may in addition receive the name of a +# configuration file, the format of which is extension-specific. +# +# Format: +#LoadExtension = "/path/to/extension" [ : "/optional/configuration/file" ] ; +# +# Examples: +#LoadExtension = "extensions/sample.fdx"; +#LoadExtension = "extensions/sample.fdx":"conf/sample.conf"; + +# Extensions are named as follow: +# dict_* for extensions that add content to the dictionary definitions. +# dbg_* for extensions useful only to retrieve more information on the framework execution. +# acl_* : Access control list, to control which peers are allowed to connect. +# rt_* : routing extensions that impact how messages are forwarded to other peers. +# app_* : applications, these extensions usually register callbacks to handle specific messages. +# test_* : dummy extensions that are useful only in testing environments. + + +# The dbg_msg_dump.fdx extension allows you to tweak the way freeDiameter displays some +# information about some events. This extension does not actually use a configuration file +# but receives directly a parameter in the string passed to the extension. Here are some examples: +## LoadExtension = "dbg_msg_dumps.fdx" : "0x1111"; # Removes all default hooks, very quiet even in case of errors. +## LoadExtension = "dbg_msg_dumps.fdx" : "0x2222"; # Display all events with few details. +## LoadExtension = "dbg_msg_dumps.fdx" : "0x0080"; # Dump complete information about sent and received messages. +# The four digits respectively control: connections, routing decisions, sent/received messages, errors. +# The values for each digit are: +# 0 - default - keep the default behavior +# 1 - quiet - remove any specific log +# 2 - compact - display only a summary of the information +# 4 - full - display the complete information on a single long line +# 8 - tree - display the complete information in an easier to read format spanning several lines. + +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dbg_msg_dumps.fdx" : "0x8888"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_rfc5777.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_mip6i.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_nasreq.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_nas_mipv6.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_dcca.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_dcca_3gpp.fdx"; + + +############################################################## +## Peers configuration + +# The local server listens for incoming connections. By default, +# all unknown connecting peers are rejected. Extensions can override this behavior (e.g., acl_wl). +# +# In addition to incoming connections, the local peer can +# be configured to establish and maintain connections to some +# Diameter nodes and allow connections from these nodes. +# This is achieved with the ConnectPeer directive described below. +# +# Note that the configured Diameter Identity MUST match +# the information received inside CEA, or the connection will be aborted. +# +# Format: +#ConnectPeer = "diameterid" [ { parameter1; parameter2; ...} ] ; +# Parameters that can be specified in the peer's parameter list: +# No_TCP; No_SCTP; No_IP; No_IPv6; Prefer_TCP; TLS_old_method; +# No_TLS; # assume transparent security instead of TLS. DTLS is not supported yet (will change in future versions). +# Port = 5868; # The port to connect to +# TcTimer = 30; +# TwTimer = 30; +# ConnectTo = "202.249.37.5"; +# ConnectTo = "2001:200:903:2::202:1"; +# TLS_Prio = "NORMAL"; +# Realm = "realm.net"; # Reject the peer if it does not advertise this realm. +# Examples: +#ConnectPeer = "aaa.wide.ad.jp"; +#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; Port=3868; } ; +ConnectPeer = "hss.EPC_DOMAIN" { ConnectTo = "HSS_IP"; Port = HSS_BIND_PORT; No_TLS; }; + + +############################################################## diff --git a/custom_deployments/open5gs_hss_cx/mme/mme.yaml b/custom_deployments/open5gs_hss_cx/mme/mme.yaml new file mode 100644 index 0000000..b98b8fb --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/mme/mme.yaml @@ -0,0 +1,59 @@ +logger: + file: + path: /open5gs/install/var/log/open5gs/mme.log + +global: + max: + ue: MAX_NUM_UE + +mme: + freeDiameter: /open5gs/install/etc/freeDiameter/mme.conf + s1ap: + server: + - dev: MME_IF + gtpc: + server: + - dev: MME_IF + client: + sgwc: + - address: SGWC_IP + smf: + - address: SMF_IP + sgsap: + server: + - address: OSMOMSC_IP + map: + tai: + plmn_id: + mcc: MCC + mnc: MNC + tac: TAC + lai: + plmn_id: + mcc: MCC + mnc: MNC + lac: 1 + gummei: + - plmn_id: + mcc: MCC + mnc: MNC + mme_gid: 2 + mme_code: 1 + tai: + - plmn_id: + mcc: MCC + mnc: MNC + tac: TAC + security: + integrity_order : [ EIA2, EIA1, EIA0 ] + ciphering_order : [ EEA0, EEA1, EEA2 ] + network_name: + full: Open5GS + mme_name: open5gs-mme0 + metrics: + server: + - address: MME_IP + port: 9091 + time: + t3412: + value: 540 diff --git a/custom_deployments/open5gs_hss_cx/mme/mme_init.sh b/custom_deployments/open5gs_hss_cx/mme/mme_init.sh new file mode 100755 index 0000000..9693b53 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/mme/mme_init.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) +export IF_NAME=$(ip r | awk '/default/ { print $5 }') + +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +cp /mnt/mme/mme.yaml install/etc/open5gs +cp /mnt/mme/mme.conf install/etc/freeDiameter +cp /mnt/mme/make_certs.sh install/etc/freeDiameter + +sed -i 's|MNC|'$MNC'|g' install/etc/open5gs/mme.yaml +sed -i 's|MCC|'$MCC'|g' install/etc/open5gs/mme.yaml +sed -i 's|TAC|'$TAC'|g' install/etc/open5gs/mme.yaml +sed -i 's|MME_IP|'$MME_IP'|g' install/etc/open5gs/mme.yaml +sed -i 's|MME_IF|'$IF_NAME'|g' install/etc/open5gs/mme.yaml +sed -i 's|OSMOMSC_IP|'$OSMOMSC_IP'|g' install/etc/open5gs/mme.yaml +sed -i 's|SGWC_IP|'$SGWC_IP'|g' install/etc/open5gs/mme.yaml +sed -i 's|SMF_IP|'$SMF_IP'|g' install/etc/open5gs/mme.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/mme.yaml +sed -i 's|MME_IP|'$MME_IP'|g' install/etc/freeDiameter/mme.conf +sed -i 's|HSS_IP|'$HSS_IP'|g' install/etc/freeDiameter/mme.conf +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' install/etc/freeDiameter/mme.conf +sed -i 's|HSS_BIND_PORT|'$HSS_BIND_PORT'|g' install/etc/freeDiameter/mme.conf +sed -i 's|LD_LIBRARY_PATH|'$LD_LIBRARY_PATH'|g' install/etc/freeDiameter/mme.conf +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' install/etc/freeDiameter/make_certs.sh + +# Generate TLS certificates +./install/etc/freeDiameter/make_certs.sh install/etc/freeDiameter + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/open5gs_hss_cx/opensips_ims_icscf/freeDiameter.conf b/custom_deployments/open5gs_hss_cx/opensips_ims_icscf/freeDiameter.conf new file mode 100644 index 0000000..b9b8c91 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/opensips_ims_icscf/freeDiameter.conf @@ -0,0 +1,14 @@ +Identity = "icscf.IMS_DOMAIN"; +Realm = "IMS_DOMAIN"; +Port = ICSCF_BIND_PORT; +ListenOn = "ICSCF_IP"; +SecPort = 0; +No_SCTP; +NoRelay; + +ConnectPeer = "hss.EPC_DOMAIN" { + Realm = "EPC_DOMAIN"; + No_TLS; + ConnectTo = "HSS_IP"; + port = HSS_BIND_PORT; +}; diff --git a/custom_deployments/open5gs_hss_cx/opensips_ims_icscf/icscf.dictionary b/custom_deployments/open5gs_hss_cx/opensips_ims_icscf/icscf.dictionary new file mode 100644 index 0000000..a6e9f04 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/opensips_ims_icscf/icscf.dictionary @@ -0,0 +1,32 @@ +VENDOR 10415 TGPP + +ATTRIBUTE Visited-Network-Identifier 600 string 10415 +ATTRIBUTE Public-Identity 601 string 10415 +ATTRIBUTE Server-Name 602 string 10415 + +APPLICATION-AUTH 16777216/10415 3GPP Cx + +REQUEST 300 User-Authorization Request +{ + Session-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Realm | REQUIRED | 1 + Vendor-Specific-Application-Id | REQUIRED | 1 + Auth-Session-State | REQUIRED | 1 + User-Name | REQUIRED | 1 + Public-Identity | REQUIRED | 1 + Visited-Network-Identifier | REQUIRED | 1 +} + +ANSWER 300 User-Authorization Answer +{ + Session-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Host | OPTIONAL | 1 + Destination-Realm | OPTIONAL | 1 + Vendor-Specific-Application-Id | REQUIRED | 1 + Auth-Session-State | REQUIRED | 1 + Experimental-Result | REQUIRED | 1 +} diff --git a/custom_deployments/open5gs_hss_cx/opensips_ims_icscf/icscf_init.sh b/custom_deployments/open5gs_hss_cx/opensips_ims_icscf/icscf_init.sh new file mode 100755 index 0000000..bee7808 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/opensips_ims_icscf/icscf_init.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +mkdir -p /etc/opensips +cp /mnt/icscf/freeDiameter.conf /etc/opensips +cp /mnt/icscf/icscf.dictionary /etc/opensips +cp /mnt/icscf/opensips.cfg /etc/opensips + +# For mi_fifo module. +mkdir -p /var/run/opensips + +sed -i 's|ICSCF_IP|'$ICSCF_IP'|g' /etc/opensips/freeDiameter.conf +sed -i 's|HSS_IP|'$HSS_IP'|g' /etc/opensips/freeDiameter.conf +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/opensips/freeDiameter.conf +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/opensips/freeDiameter.conf +sed -i 's|HSS_BIND_PORT|'$HSS_BIND_PORT'|g' /etc/opensips/freeDiameter.conf +sed -i 's|ICSCF_BIND_PORT|'$ICSCF_BIND_PORT'|g' /etc/opensips/freeDiameter.conf + +sed -i 's|ICSCF_IP|'$ICSCF_IP'|g' /etc/opensips/opensips.cfg +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/opensips/opensips.cfg +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/opensips/opensips.cfg + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +exec opensips -f /etc/opensips/opensips.cfg -F $@ diff --git a/custom_deployments/open5gs_hss_cx/opensips_ims_icscf/opensips.cfg b/custom_deployments/open5gs_hss_cx/opensips_ims_icscf/opensips.cfg new file mode 100644 index 0000000..482594f --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/opensips_ims_icscf/opensips.cfg @@ -0,0 +1,226 @@ +# +# OpenSIPS residential configuration script +# by OpenSIPS Solutions +# +# This script was generated via "make menuconfig", from +# the "Residential" scenario. +# You can enable / disable more features / functionalities by +# re-generating the scenario with different options.# +# +# Please refer to the Core CookBook at: +# https://opensips.org/Resources/DocsCookbooks +# for a explanation of possible statements, functions and parameters. +# + + +####### Global Parameters ######### + +/* uncomment the following lines to enable debugging */ +#debug_mode=yes + +log_level=3 +xlog_level=3 +log_stderror=yes +log_stdout=yes +log_facility=LOG_LOCAL0 + +udp_workers=4 + +/* uncomment the next line to enable the auto temporary blacklisting of + not available destinations (default disabled) */ +#disable_dns_blacklist=no + +/* uncomment the next line to enable IPv6 lookup after IPv4 dns + lookup failures (default disabled) */ +#dns_try_ipv6=yes + + +socket=udp:ICSCF_IP:4060 +socket=tcp:ICSCF_IP:4060 + +alias="icscf.IMS_DOMAIN" + +#set module path +mpath="/usr/local/opensips/modules" + +####### Modules Section ######## +####### http module ###### +loadmodule "httpd.so" + +modparam("httpd", "ip", "ICSCF_IP") +modparam("httpd", "port", 8080) + + +#### SIGNALING module +loadmodule "signaling.so" + +#### StateLess module +loadmodule "sl.so" + +#### Transaction Module +loadmodule "tm.so" +modparam("tm", "fr_timeout", 5) +modparam("tm", "fr_inv_timeout", 30) +modparam("tm", "restart_fr_on_each_reply", 0) +modparam("tm", "onreply_avp_mode", 1) + +#### Record Route Module +loadmodule "rr.so" +/* do not append from tag to the RR (no need for this script) */ +modparam("rr", "append_fromtag", 0) + +#### MAX ForWarD module +loadmodule "maxfwd.so" + +#### SIP MSG OPerationS module +loadmodule "sipmsgops.so" + +#### FIFO Management Interface +loadmodule "mi_fifo.so" +modparam("mi_fifo", "fifo_name", "/var/run/opensips/opensips_fifo") +modparam("mi_fifo", "fifo_mode", 0666) + +#### USeR LOCation module +loadmodule "usrloc.so" +modparam("usrloc", "nat_bflag", "NAT") +modparam("usrloc", "working_mode_preset", "single-instance-no-db") + +#### REGISTRAR module +loadmodule "registrar.so" +modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT") +/* uncomment the next line not to allow more than 10 contacts per AOR */ +#modparam("registrar", "max_contacts", 10) + +#### ACCounting module +loadmodule "acc.so" +/* what special events should be accounted ? */ +modparam("acc", "early_media", 0) +modparam("acc", "report_cancels", 0) +/* by default we do not adjust the direct of the sequential requests. + if you enable this parameter, be sure to enable "append_fromtag" + in "rr" module */ +modparam("acc", "detect_direction", 0) + +loadmodule "proto_udp.so" +loadmodule "proto_tcp.so" + +#### aaa_diameter module +loadmodule "aaa_diameter.so" +modparam("aaa_diameter", "fd_log_level", 1) # max amount of logging, quite annoying +modparam("aaa_diameter", "realm", "EPC_DOMAIN") +modparam("aaa_diameter", "peer_identity", "hss") +modparam("aaa_diameter", "aaa_url", + "diameter:/etc/opensips/freeDiameter.conf;extra-avps-file:/etc/opensips/icscf.dictionary") + +#### JSON module +loadmodule "json.so" + + + +####### Routing Logic ######## + +# main request routing logic + +route{ + xlog("L_INFO", "[$ci] Start route time [$Tf] method ($rm) r-uri ($ru) \n"); + + if (!mf_process_maxfwd_header(10)) { + send_reply(483,"Too Many Hops"); + exit; + } + + if (has_totag()) { + + # handle hop-by-hop ACK (no routing required) + if ( is_method("ACK") && t_check_trans() ) { + t_relay(); + exit; + } + + # sequential request within a dialog should + # take the path determined by record-routing + if ( !loose_route() ) { + # we do record-routing for all our traffic, so we should not + # receive any sequential requests without Route hdr. + send_reply(404,"Not here"); + exit; + } + + if (is_method("BYE")) { + # do accounting even if the transaction fails + do_accounting("log","failed"); + } + + # route it out to whatever destination was set by loose_route() + # in $du (destination URI). + route(relay); + exit; + } + + # CANCEL processing + if (is_method("CANCEL")) { + if (t_check_trans()) + t_relay(); + exit; + } + + # absorb retransmissions, but do not create transaction + t_check_trans(); + + if (is_method("REGISTER")) { + xlog("L_INFO", "[$ci] Received REGISTER for $tu - doing UAR\n"); + + $var(payload) = "[ + { \"Session-Id\": \"icscf.IMS_DOMAIN;"+$Ts+"."+$Tsm+";"+$pp+"\" }, + { \"Origin-Host\": \"icscf.IMS_DOMAIN\" }, + { \"Origin-Realm\": \"IMS_DOMAIN\" }, + { \"Destination-Realm\": \"EPC_DOMAIN\" }, + { \"Vendor-Specific-Application-Id\": [{\"Vendor-Id\": 10415}, + {\"Auth-Application-Id\": 16777216}]}, + { \"Auth-Session-State\": 1 }, + { \"User-Name\": \""+$fU+"@"+$fd+"\" }, + { \"Public-Identity\": \""+$fu+"\" }, + { \"Visited-Network-Identifier\": \"IMS_DOMAIN\" } + ]"; + + $var(rc) = dm_send_request(16777216, 300, $var(payload), $var(rpl_avps)); + xlog("[$ci] UAA rc: $var(rc), UAA AVPs: $var(rpl_avps)\n"); + + $var(server_name) = NULL; + $json(rpl_avps) := $var(rpl_avps); + for ($var(item) in $(json(rpl_avps)[*])) { + $json(item) := $var(item); + for ($var(key) in $(json(item.keys)[*])) { + if ($var(key) == "Server-Name") { + $var(server_name) = $json(item/$var(key)); + break; + } + } + if ($var(server_name) != NULL) + break; + } + + if ($var(server_name) == NULL) { + xlog("L_ERR", "[$ci] No server available! Relaying to default S-CSCF\n"); + $var(server_name) = "sip:scscf.IMS_DOMAIN:6060"; + } + + # relay to S-CSCF + xlog("L_INFO", "[$ci] using S-CSCF $var(server_name)\n"); + $ru = $var(server_name); + + route(relay); + exit; + } + + send_reply(503,"Not Implemented"); + exit; +} + + +route[relay] { + if (!t_relay()) { + send_reply(500,"Internal Error"); + } + exit; +} diff --git a/custom_deployments/open5gs_hss_cx/opensips_ims_scscf/freeDiameter.conf b/custom_deployments/open5gs_hss_cx/opensips_ims_scscf/freeDiameter.conf new file mode 100644 index 0000000..ee97c1e --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/opensips_ims_scscf/freeDiameter.conf @@ -0,0 +1,14 @@ +Identity = "scscf.IMS_DOMAIN"; +Realm = "IMS_DOMAIN"; +Port = SCSCF_BIND_PORT; +ListenOn = "SCSCF_IP"; +SecPort = 0; +No_SCTP; +NoRelay; + +ConnectPeer = "hss.EPC_DOMAIN" { + Realm = "EPC_DOMAIN"; + No_TLS; + ConnectTo = "HSS_IP"; + port = HSS_BIND_PORT; +}; diff --git a/custom_deployments/open5gs_hss_cx/opensips_ims_scscf/opensips.cfg b/custom_deployments/open5gs_hss_cx/opensips_ims_scscf/opensips.cfg new file mode 100644 index 0000000..8c0b6bd --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/opensips_ims_scscf/opensips.cfg @@ -0,0 +1,311 @@ +# +# OpenSIPS residential configuration script +# by OpenSIPS Solutions +# +# This script was generated via "make menuconfig", from +# the "Residential" scenario. +# You can enable / disable more features / functionalities by +# re-generating the scenario with different options.# +# +# Please refer to the Core CookBook at: +# https://opensips.org/Resources/DocsCookbooks +# for a explanation of possible statements, functions and parameters. +# + + +####### Global Parameters ######### + +/* uncomment the following lines to enable debugging */ +#debug_mode=yes + +log_level=3 +xlog_level=3 +log_stderror=yes +log_stdout=yes +xlog_buf_size=16384 +log_facility=LOG_LOCAL0 + +udp_workers=4 + +/* uncomment the next line to enable the auto temporary blacklisting of + not available destinations (default disabled) */ +#disable_dns_blacklist=no + +/* uncomment the next line to enable IPv6 lookup after IPv4 dns + lookup failures (default disabled) */ +#dns_try_ipv6=yes + + +socket=udp:SCSCF_IP:6060 +socket=tcp:SCSCF_IP:6060 + +alias="scscf.IMS_DOMAIN" + +#set module path +mpath="/usr/local/opensips/modules" + +####### Modules Section ######## + +#### MYSQL module +loadmodule "db_mysql.so" + +#### SIGNALING module +loadmodule "signaling.so" + +#### StateLess module +loadmodule "sl.so" + +#### Transaction Module +loadmodule "tm.so" +modparam("tm", "fr_timeout", 5) +modparam("tm", "fr_inv_timeout", 30) +modparam("tm", "restart_fr_on_each_reply", 0) +modparam("tm", "onreply_avp_mode", 1) + +#### Record Route Module +loadmodule "rr.so" +/* do not append from tag to the RR (no need for this script) */ +modparam("rr", "append_fromtag", 0) + +#### MAX ForWarD module +loadmodule "maxfwd.so" + +#### SIP MSG OPerationS module +loadmodule "sipmsgops.so" + +#### FIFO Management Interface +loadmodule "mi_fifo.so" +modparam("mi_fifo", "fifo_name", "/var/run/opensips/opensips_fifo") +modparam("mi_fifo", "fifo_mode", 0666) + +#### USeR LOCation module +loadmodule "usrloc.so" +modparam("usrloc", "nat_bflag", "NAT") +modparam("usrloc", "working_mode_preset", "single-instance-no-db") + +#### REGISTRAR module +loadmodule "registrar.so" +modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT") +modparam("registrar", "attr_avp", "$avp(attr)") +/* uncomment the next line not to allow more than 10 contacts per AOR */ +#modparam("registrar", "max_contacts", 10) + +#### ACCounting module +loadmodule "acc.so" +/* what special events should be accounted ? */ +modparam("acc", "early_media", 0) +modparam("acc", "report_cancels", 0) +/* by default we do not adjust the direct of the sequential requests. + if you enable this parameter, be sure to enable "append_fromtag" + in "rr" module */ +modparam("acc", "detect_direction", 0) + +loadmodule "proto_udp.so" +loadmodule "proto_tcp.so" + +#### aaa_diameter module +loadmodule "aaa_diameter.so" +modparam("aaa_diameter", "fd_log_level", 1) # max amount of logging, quite annoying +modparam("aaa_diameter", "realm", "EPC_DOMAIN") +modparam("aaa_diameter", "peer_identity", "hss") +modparam("aaa_diameter", "aaa_url", + "diameter:/etc/opensips/freeDiameter.conf;extra-avps-file:/etc/opensips/scscf.dictionary") +loadmodule "auth_aka.so" +modparam("auth_aka", "default_av_mgm", "diameter") +modparam("auth_aka", "default_qop", "auth") +loadmodule "aka_av_diameter.so" +modparam("aka_av_diameter", "realm", + "scscf.IMS_DOMAIN") +modparam("aka_av_diameter", "aaa_url", + "diameter:/etc/opensips/freeDiameter.conf;extra-avps-file:/etc/opensips/scscf.dictionary") + +#### dialplan module +loadmodule "dialplan.so" +modparam("dialplan","db_url", "mysql://opensips_scscf:heslo@MYSQL_IP/opensips_scscf") + + +#### auth module +loadmodule "auth.so" + +#### JSON module +loadmodule "json.so" + +#### XML module +loadmodule "xml.so" + + + +####### Routing Logic ######## + +# main request routing logic + +route{ + xlog("L_INFO", "[$ci] Start route time [$Tf] method ($rm) r-uri ($ru) \n"); + + if (!mf_process_maxfwd_header(10)) { + send_reply(483,"Too Many Hops"); + exit; + } + + if (has_totag()) { + + # handle hop-by-hop ACK (no routing required) + if ( is_method("ACK") && t_check_trans() ) { + t_relay(); + exit; + } + + # sequential request within a dialog should + # take the path determined by record-routing + if ( !loose_route() ) { + # we do record-routing for all our traffic, so we should not + # receive any sequential requests without Route hdr. + send_reply(404,"Not here"); + exit; + } + + if (is_method("BYE")) { + # do accounting even if the transaction fails + do_accounting("log","failed"); + } + + # route it out to whatever destination was set by loose_route() + # in $du (destination URI). + route(relay); + exit; + } + + # CANCEL processing + if (is_method("CANCEL")) { + if (t_check_trans()) + t_relay(); + exit; + } + + # absorb retransmissions, but do not create transaction + t_check_trans(); + + if (is_method("REGISTER")) { + xlog("L_INFO", "[$ci] Received REGISTER for $tu - doing authorization\n"); + if (!aka_www_authorize()) { + if (!async(aka_www_challenge(), aka_resume_mar)) + t_reply(500, "Internal Error"); + exit; + } + xlog("L_INFO", "[$ci] Received REGISTER for $tu - authorized, doing SAR\n"); + $var(payload) = "[ + { \"Session-Id\": \"scscf.IMS_DOMAIN;"+$Ts+"."+$Tsm+";"+$pp+"\" }, + { \"Origin-Host\": \"scscf.IMS_DOMAIN\" }, + { \"Origin-Realm\": \"IMS_DOMAIN\" }, + { \"Destination-Realm\": \"EPC_DOMAIN\" }, + { \"Vendor-Specific-Application-Id\": [{\"Vendor-Id\": 10415}, + {\"Auth-Application-Id\": 16777216}]}, + { \"Auth-Session-State\": 1 }, + { \"User-Name\": \""+$fU+"@"+$fd+"\" }, + { \"Public-Identity\": \""+$fu+"\" }, + { \"Server-Assignment-Type\": 1 }, + { \"User-Data-Already-Available\": 0}, + { \"Server-Name\": \"sip:scscf.IMS_DOMAIN:6060\" } + ]"; + + if (!async(dm_send_request(16777216, 301, $var(payload), $var(rpl_avps)), aka_resume_sar)) { + t_reply(500, "Internal Error"); + exit; + } + exit; + } else if (is_method("INVITE")) { + + xlog("L_INFO", "[$ci] Received INVITE for $tu/$ru - checking dialplan\n"); + loose_route(); # consume preloaded routes + if (!record_route()) { + xlog("L_ERR", "[$ci] Cannot do record_route()\n"); + t_reply(503, "Internal Error"); + exit; + } + if ($ru =~ "^tel:") { + $var(tel_user) = $rU; + $var(tel_domain) = $(ru{uri.param,phone-context}); + $ru = "sip:" + $var(tel_user) + "@" + $var(tel_domain); + } else { + $rU = $(rU{s.select,0,;}); + } + if (!dp_translate(1, $rU, $var(dialplan))) { + $var(dialplan) = "USER"; + xlog("L_DBG", "[$ci] unknown dialplan - considering $var(dialplan)\n"); + } + xlog("L_INFO", "[$ci] Dial $rU is a $var(dialplan) dialplan\n"); + switch ($var(dialplan)) { + case "USER": + xlog("L_INFO", "[$ci] lookup user $rU/$(oU{s.select,0,;})\n"); + if (!lookup("location")) { + xlog("L_ERR", "[$ci] Received INVITE for $tu/$ru not registered - sending to service\n"); + t_reply(404, "User not found"); + exit; + } + break; + case "SERVICE": + # TODO: handle service + case "APPLICATION": + # TODO: handle application server + default: + xlog("L_ERR", "[$ci] unknown $var(dialplan) dialplan\n"); + t_reply(503, "Unknown dialplan"); + exit; + } + if (!t_relay()) { + xlog("L_ERR", "[$ci] Cannot relay to $ru\n"); + t_reply(503, "Internal Error"); + } + exit; + } + + send_reply(503,"Not Implemented"); + exit; +} + + +route[relay] { + if (!t_relay()) { + send_reply(500,"Internal Error"); + } + exit; +} + +route[aka_resume_mar] { + xlog("L_DBG", "[$ci] MAA rc: $rc\n"); +} + +route[aka_resume_sar] { + xlog("[$ci] SAA rc: $var(rc), SAA AVPs: $var(rpl_avps)\n"); + $avp(attr) = $ct.fields(params); + append_to_reply("Service-Route: \r\n"); + $json(rpl_avps) := $var(rpl_avps); + for ($var(item) in $(json(rpl_avps)[*])) { + $json(item) := $var(item); + for ($var(key) in $(json(item.keys)[*])) { + if ($var(key) == "Cx-User-Data") { + $xml(data) := $json(item/$var(key)); + $xml(profile) := $xml(data/IMSSubscription/ServiceProfile); + $var(idx) = 0; + while ($xml(profile/ServiceProfile/PublicIdentity[$var(idx)]) != NULL) { + append_to_reply("P-Associated-URI: <$xml(profile/ServiceProfile/PublicIdentity[$var(idx)]/Identity.val)>\r\n"); + $var(uri) = $xml(profile/ServiceProfile/PublicIdentity[$var(idx)]/Identity.val); + if ($var(uri) == $tu) { + # Save AoR for IMPU in format sip:IMSI@IMS_DOMAIN and send 200 response. + if (!save("location", "path-lazy")) { + t_reply(503, "Internal Error"); + exit; + } + } else { + # Save AoR for IMPU in other formats and dont send response. + if (!save("location", "no-reply, path-lazy", $var(uri))) { + t_reply(503, "Internal Error"); + exit; + } + } + $var(idx) = $var(idx) + 1; + } + } + } + } +} diff --git a/custom_deployments/open5gs_hss_cx/opensips_ims_scscf/scscf.dictionary b/custom_deployments/open5gs_hss_cx/opensips_ims_scscf/scscf.dictionary new file mode 100644 index 0000000..8ae2a37 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/opensips_ims_scscf/scscf.dictionary @@ -0,0 +1,105 @@ +VENDOR 10415 TGPP + +ATTRIBUTE Visited-Network-Identifier 600 string 10415 +ATTRIBUTE Public-Identity 601 string 10415 +ATTRIBUTE Server-Name 602 string 10415 +ATTRIBUTE Mandatory-Capability 604 unsigned32 10415 +ATTRIBUTE Optional-Capability 605 unsigned32 10415 +ATTRIBUTE Cx-User-Data 606 string 10415 +ATTRIBUTE 3GPP-SIP-Number-Auth-Items 607 unsigned32 10415 +ATTRIBUTE 3GPP-SIP-Authentication-Scheme 608 utf8string 10415 +ATTRIBUTE 3GPP-SIP-Authenticate 609 hexstring 10415 +ATTRIBUTE 3GPP-SIP-Authorization 610 hexstring 10415 +ATTRIBUTE 3GPP-SIP-Authentication-Context 611 string 10415 +ATTRIBUTE 3GPP-SIP-Item-Number 613 unsigned32 10415 +ATTRIBUTE Server-Assignment-Type 614 unsigned32 10415 +ATTRIBUTE User-Data-Already-Available 624 unsigned32 10415 +ATTRIBUTE Confidentiality-Key 625 hexstring 10415 +ATTRIBUTE Integrity-Key 626 hexstring 10415 + +ATTRIBUTE Primary-Event-Charging-Function-Name 619 string 10415 +ATTRIBUTE Secondary-Event-Charging-Function-Name 620 string 10415 +ATTRIBUTE Primary-Charging-Collection-Function-Name 621 string 10415 +ATTRIBUTE Secondary-Charging-Collection-Function-Name 622 string 10415 + +ATTRIBUTE 3GPP-SIP-Auth-Data-Item 612 grouped 10415 +{ + 3GPP-SIP-Item-Number | OPTIONAL | 1 + 3GPP-SIP-Authentication-Scheme | OPTIONAL | 1 + 3GPP-SIP-Authenticate | OPTIONAL | 1 + 3GPP-SIP-Authorization | OPTIONAL | 1 + 3GPP-SIP-Authentication-Context | OPTIONAL | 1 + Confidentiality-Key | OPTIONAL | 1 + Integrity-Key | OPTIONAL | 1 +} + +ATTRIBUTE Charging-Information 618 grouped 10415 +{ + Primary-Event-Charging-Function-Name | OPTIONAL | 1 + Secondary-Event-Charging-Function-Name | OPTIONAL | 1 + Primary-Charging-Collection-Function-Name | OPTIONAL | 1 + Secondary-Charging-Collection-Function-Name | OPTIONAL | 1 +} + + +APPLICATION-AUTH 16777216/10415 3GPP Cx + +REQUEST 301 Server-Assignment Request +{ + Session-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Realm | REQUIRED | 1 + Vendor-Specific-Application-Id | REQUIRED | 1 + Auth-Session-State | REQUIRED | 1 + Public-Identity | REQUIRED | 1 + Server-Name | REQUIRED | 1 + User-Name | REQUIRED | 1 + Server-Assignment-Type | REQUIRED | 1 + User-Data-Already-Available | REQUIRED | 1 +} + +ANSWER 301 Server-Assignment Answer +{ + Session-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Host | OPTIONAL | 1 + Destination-Realm | OPTIONAL | 1 + Vendor-Specific-Application-Id | REQUIRED | 1 + Auth-Session-State | REQUIRED | 1 + User-Name | REQUIRED | 1 + Cx-User-Data | REQUIRED | 1 + Charging-Information | OPTIONAL | 1 + Result-Code | REQUIRED | 1 +} + +REQUEST 303 Multimedia-Auth Request +{ + Session-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Realm | REQUIRED | 1 + Vendor-Specific-Application-Id | REQUIRED | 1 + Auth-Session-State | REQUIRED | 1 + Public-Identity | REQUIRED | 1 + 3GPP-SIP-Number-Auth-Items | REQUIRED | 1 + 3GPP-SIP-Auth-Data-Item | REQUIRED | 1 + Server-Name | REQUIRED | 1 +} + +ANSWER 303 Multimedia-Auth Answer +{ + Session-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Host | OPTIONAL | 1 + Destination-Realm | OPTIONAL | 1 + Vendor-Specific-Application-Id | REQUIRED | 1 + Auth-Session-State | REQUIRED | 1 + Public-Identity | REQUIRED | 1 + 3GPP-SIP-Number-Auth-Items | REQUIRED | 1 + 3GPP-SIP-Auth-Data-Item | REQUIRED | 1 + User-Name | REQUIRED | 1 + Result-Code | REQUIRED | 1 +} diff --git a/custom_deployments/open5gs_hss_cx/opensips_ims_scscf/scscf_init.sh b/custom_deployments/open5gs_hss_cx/opensips_ims_scscf/scscf_init.sh new file mode 100755 index 0000000..c909fff --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/opensips_ims_scscf/scscf_init.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +mkdir -p /etc/opensips +cp /mnt/scscf/freeDiameter.conf /etc/opensips +cp /mnt/scscf/scscf.dictionary /etc/opensips +cp /mnt/scscf/opensips.cfg /etc/opensips + +# For mi_fifo module. +mkdir -p /var/run/opensips + +while ! mysqladmin ping -h ${MYSQL_IP} --silent; do + sleep 5; +done + +# Sleep until permissions are set +sleep 10; + +# Create SCSCF database, populate tables and grant privileges +if [[ -z "`mysql -u root -h ${MYSQL_IP} -qfsBe "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='opensips_scscf'" 2>&1`" ]]; +then + mysql -u root -h ${MYSQL_IP} -e "create database opensips_scscf;" + mysql -u root -h ${MYSQL_IP} opensips_scscf < /usr/local/share/opensips/mysql/standard-create.sql + mysql -u root -h ${MYSQL_IP} opensips_scscf < /usr/local/share/opensips/mysql/dialplan-create.sql + SCSCF_USER_EXISTS=`mysql -u root -h ${MYSQL_IP} -s -N -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE User = 'opensips_scscf' AND Host = '%')"` + if [[ "$SCSCF_USER_EXISTS" == 0 ]] + then + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'opensips_scscf'@'%' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'opensips_scscf'@'$SCSCF_IP' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON opensips_scscf.* TO 'opensips_scscf'@'%'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON opensips_scscf.* TO 'opensips_scscf'@'$SCSCF_IP'"; + mysql -u root -h ${MYSQL_IP} -e "FLUSH PRIVILEGES;" + fi +fi + +sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' /etc/opensips/freeDiameter.conf +sed -i 's|HSS_IP|'$HSS_IP'|g' /etc/opensips/freeDiameter.conf +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/opensips/freeDiameter.conf +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/opensips/freeDiameter.conf +sed -i 's|HSS_BIND_PORT|'$HSS_BIND_PORT'|g' /etc/opensips/freeDiameter.conf +sed -i 's|SCSCF_BIND_PORT|'$SCSCF_BIND_PORT'|g' /etc/opensips/freeDiameter.conf + +sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' /etc/opensips/opensips.cfg +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/opensips/opensips.cfg +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/opensips/opensips.cfg +sed -i 's|MYSQL_IP|'$MYSQL_IP'|g' /etc/opensips/opensips.cfg + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +exec opensips -f /etc/opensips/opensips.cfg -F $@ diff --git a/custom_deployments/open5gs_hss_cx/scscf/CxDataType_Rel6.xsd b/custom_deployments/open5gs_hss_cx/scscf/CxDataType_Rel6.xsd new file mode 100644 index 0000000..3eb21b7 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/scscf/CxDataType_Rel6.xsd @@ -0,0 +1,293 @@ + + + + + + + + + + + + + + + iFC is part of the registered profile + + + + + + + + iFC is part of the unregistered profile + + + + + + + + + + + + + + + + + + + + + + + Matches to REGISTER messages that are related to initial registration + + + + + + + + Matches to REGISTER messages that are related to re-registration + + + + + + + + Matches to REGISTER messages that are related to de-registration + + + + + + + + + + + + + Session Continued + + + + + + + + Session Terminated + + + + + + + + + + + + + Originating Session + + + + + + + + Terminating Session for registered user + + + + + + + + Terminating Session for unregistered user + + + + + + + + + + + + + + + + + + + + + + + + + + Identity is a Public User Identity. + + + + + + + + Identity is a distinct Public Service Identity. + + + + + + + + Identity matches a wildcarded Public Service Identity. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/custom_deployments/open5gs_hss_cx/scscf/CxDataType_Rel7.xsd b/custom_deployments/open5gs_hss_cx/scscf/CxDataType_Rel7.xsd new file mode 100644 index 0000000..b9289e2 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/scscf/CxDataType_Rel7.xsd @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + iFC is part of the registered profile + + + + + + + + iFC is part of the unregistered profile + + + + + + + + + + + + + + + + + + + + + + + Matches to REGISTER messages that are related to initial registration + + + + + + + + Matches to REGISTER messages that are related to re-registration + + + + + + + + Matches to REGISTER messages that are related to de-registration + + + + + + + + + + + + + Session Continued + + + + + + + + Session Terminated + + + + + + + + + + + + + Originating Session + + + + + + + + Terminating Session for registered user + + + + + + + + Terminating Session for unregistered user + + + + + + + + Originating Session for an unregistered user + + + + + + + + + + + + + + + + + + + + + + + + + + Identity is a Public User Identity. + + + + + + + + Identity is a distinct Public Service Identity. + + + + + + + + Identity matches a wildcarded Public Service Identity. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/custom_deployments/open5gs_hss_cx/scscf/CxDataType_Rel8.xsd b/custom_deployments/open5gs_hss_cx/scscf/CxDataType_Rel8.xsd new file mode 100644 index 0000000..2e057eb --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/scscf/CxDataType_Rel8.xsd @@ -0,0 +1,379 @@ + + + + + + + + + + + + + + + iFC is part of the registered profile + + + + + + + + iFC is part of the unregistered profile + + + + + + + + + + + + + + + + + + + + + + + Matches to REGISTER messages that are related to initial registration + + + + + + + + Matches to REGISTER messages that are related to re-registration + + + + + + + + Matches to REGISTER messages that are related to de-registration + + + + + + + + + + + + + Session Continued + + + + + + + + Session Terminated + + + + + + + + + + + + + Originating Session + + + + + + + + Terminating Session for registered user + + + + + + + + Terminating Session for unregistered user + + + + + + + + Originating Session for an unregistered user + + + + + + + + + + + + + + + + + + + + + + + + + + Identity is a Public User Identity. + + + + + + + + Identity is a distinct Public Service Identity. + + + + + + + + Identity matches a wildcarded Public Service Identity. + + + + + + + + Identity is a Wildcarded Public User Identity. + + + + + + + + Identity is a Wildcard for Public User Identities. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/custom_deployments/open5gs_hss_cx/scscf/dispatcher.list b/custom_deployments/open5gs_hss_cx/scscf/dispatcher.list new file mode 100644 index 0000000..7e4bb16 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/scscf/dispatcher.list @@ -0,0 +1 @@ +# ng-voice Interconnect diff --git a/custom_deployments/open5gs_hss_cx/scscf/kamailio_scscf.cfg b/custom_deployments/open5gs_hss_cx/scscf/kamailio_scscf.cfg new file mode 100644 index 0000000..2fac4ce --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/scscf/kamailio_scscf.cfg @@ -0,0 +1,1281 @@ +#!KAMAILIO +# +# This config file implements the basic P-CSCF functionality +# - web: http://www.kamailio.org +# - git: http://sip-router.org +# +# Refer to the Core CookBook at http://www.kamailio.org/dokuwiki/doku.php +# for an explanation of possible statements, functions and parameters. +# +# Direct your questions about this file to: . +# +# For more information about the various parameters, functions and statements +# try http://sip-router.org/wiki/ . +# + +####### Defined Values ######### +# *** Value defines - IDs used later in config + +# - flags +# FLT_ - per transaction (message) flags +# FLB_ - per branch flags + +#!define FLT_CAPTURE 1 +#!define FLT_DIALOG 2 + +#!define DLG_TIMEOUT_AVP "i:1" +#!define RR_CUSTOM_USER_AVP "i:2" +#!define DISPATCHER_DST_AVP "i:3" +#!define DISPATCHER_GRP_AVP "i:4" +#!define DISPATCHER_CNT_AVP "i:5" +#!define DISPATCHER_SOCK_AVP "i:6" + +####### Global Parameters ######### + +include_file "scscf.cfg" + +debug=2 +log_stderror=no +sip_warning=no + +#!ifdef WITH_XMLRPC +listen=tcp:127.0.0.1:6060 +#!endif + +alias=HOSTNAME + +user_agent_header="User-Agent: Kamailio S-CSCF" +server_header="Server: Kamailio S-CSCF" +log_name="scscf" +log_prefix_mode=1 +log_prefix="{$mt $hdr(CSeq) $ci $cfg(route)} " + +/* comment the next line to enable the auto discovery of local aliases + based on reverse DNS on IPs (default on) */ +auto_aliases=no + +check_via=no # (cmd. line: -v) +dns=no # (cmd. line: -r) +rev_dns=no # (cmd. line: -R) + +# Do SRV-Loadbalancing: +dns_srv_lb=on +# Always: Also try IPv6: +dns_try_ipv6=on +# Always prefer IPv6: +dns_cache_flags=4 +# DNS-Based failover +use_dns_failover=on +# Query NAPTR-Records as well: +dns_try_naptr=on +# DNS cache won't be used (all dns lookups will result into a DNS request) +use_dns_cache=off + +#!ifdef WITH_XMLRPC +#!ifndef WITH_TCP +#!define WITH_TCP +#!endif +#!ifndef TCP_PROCESSES +# Number of TCP Processes +#!define TCP_PROCESSES 3 +#!endif +#!endif + +#!ifdef WITH_TCP +# life time of TCP connection when there is no traffic +# - a bit higher than registration expires to cope with UA behind NAT +tcp_connection_lifetime=UE_SUBSCRIPTION_EXPIRES +#!ifdef TCP_PROCESSES +tcp_children=TCP_PROCESSES +#!endif +#!else +disable_tcp=yes +#!endif + +children=4 + +system.shutdownmode = 0 desc "System shutdown mode" +system.service = "Serving-CSCF" desc "Function of this server" + +# ------------------ module loading ---------------------------------- +mpath="/usr/lib64/kamailio/modules_k/:/usr/lib64/kamailio/modules/:/usr/lib/kamailio/modules_k/:/usr/lib/kamailio/modules/:/usr/lib/x86_64-linux-gnu/kamailio/modules/:/usr/local/lib64/kamailio/modules" +# (we try both the lib64 and the lib directory) + +loadmodule "tm.so" +loadmodule "pv.so" +loadmodule "sl.so" +loadmodule "rr.so" +loadmodule "ims_dialog.so" +loadmodule "textops.so" +loadmodule "textopsx.so" +loadmodule "maxfwd.so" +loadmodule "xlog.so" +loadmodule "sanity.so" +loadmodule "siputils.so" +loadmodule "kex.so" +loadmodule "corex.so" +loadmodule "tmx.so" +loadmodule "pike.so" +#!ifdef DB_URL +loadmodule "presence" +#!endif + +#!ifdef DB_URL +loadmodule "db_mysql" +#!ifdef DB_URL2 +loadmodule "db_cluster" +#!endif +#!endif + +loadmodule "dispatcher" + +loadmodule "enum" +loadmodule "uac" + +# Control interfaces: +loadmodule "ctl" +loadmodule "cfg_rpc" +#!ifdef WITH_XMLRPC +loadmodule "xmlrpc" +#!endif + +loadmodule "cdp.so" +loadmodule "cdp_avp.so" + +loadmodule "ims_usrloc_scscf.so" +loadmodule "ims_registrar_scscf.so" +loadmodule "ims_auth.so" +loadmodule "ims_isc.so" + +#!ifdef WITH_RO +loadmodule "ims_charging.so" +#!endif + +#!ifdef CAPTURE_NODE +loadmodule "siptrace.so" +#!endif + +##!ifdef WITH_DEBUG +loadmodule "debugger.so" +modparam("debugger", "mod_hash_size", 5) +modparam("debugger", "mod_level_mode", 1) +modparam("debugger", "mod_level", "xlog=3") +modparam("debugger", "mod_level", "ims_usrloc_scscf=3") +modparam("debugger", "mod_level", "ims_registrar_scscf=3") +modparam("debugger", "mod_level", "ims_auth=3") +modparam("debugger", "mod_level", "ims_isc=3") +modparam("debugger", "mod_level", "ims_dialog=3") +modparam("debugger", "mod_level", "ims_charging=3") +##!endif + +# ----------------- setting module-specific parameters --------------- +#!ifdef DB_URL2 +# ----- db_cluster params ----- +modparam("db_cluster", "connection", DB_URL) +modparam("db_cluster", "connection", DB_URL2) +modparam("db_cluster", "cluster", "cluster1=>con1=2s2s;con2=1s1s") +#!endif + +# ----- presence params ----- +#!ifdef DB_URL +#!ifdef DB_URL2 +modparam("presence", "db_url", "cluster://cluster1") +#!else +modparam("presence", "db_url", DB_URL) +#!endif +#modparam("presence", "fallback2db", 1) +modparam("presence", "db_update_period", 20) +#!endif + +loadmodule "jsonrpcs.so" +# ----- jsonrpcs params ----- +modparam("jsonrpcs", "pretty_format", 1) +/* set the path to RPC fifo control file */ +modparam("jsonrpcs", "fifo_name", "/var/run/kamailio/kamailio_rpc.fifo") +/* set the path to RPC unix socket control file */ +modparam("jsonrpcs", "dgram_socket", "/var/run/kamailio/kamailio_rpc.sock") + +# ----- ctl params ----- +modparam("ctl", "binrpc", "unix:/var/run/kamailio/kamailio_ctl") + +# ----- tm params ----- +# auto-discard branches from previous serial forking leg +modparam("tm", "failure_reply_mode", 3) +# default retransmission timeout: 10sec +modparam("tm", "fr_timer", 10000) +# default invite retransmission timeout after 1xx: 120sec +modparam("tm", "fr_inv_timer", 120000) +# Don't reply automatically with "100 Trying" +modparam("tm", "auto_inv_100", 0) + +# ----- rr params ----- +# add value to ;lr param to cope with most of the UAs +modparam("rr", "enable_full_lr", 1) +# append from tag to the RR +modparam("rr", "append_fromtag", 1) +# add a Username to RR-Header +modparam("rr", "add_username", 1) +# Take User from a custom AVP +modparam("rr", "custom_user_avp", "$avp(RR_CUSTOM_USER_AVP)") + +# -- usrloc params -- +modparam("ims_usrloc_scscf", "enable_debug_file", 0) +modparam("ims_usrloc_scscf", "matching_mode", 0) +# Set to one as a workaround for multiple contacts created due to unstable radio link. +modparam("ims_usrloc_scscf", "maxcontact", 1) +# Set to one as a workaround for multiple contacts created due to unstable radio link. +modparam("ims_usrloc_scscf", "maxcontact_3gpp", 1) +modparam("ims_registrar_scscf", "max_contacts", 5) +modparam("ims_usrloc_scscf", "maxcontact_behaviour", 2) #overwrite +#!ifdef DB_URL +#!ifdef DB_URL2 +modparam("ims_usrloc_scscf", "db_url", "cluster://cluster1") +#!else +modparam("ims_usrloc_scscf", "db_url", DB_URL) +#!endif +modparam("ims_usrloc_scscf", "db_mode", 0) +#!endif +modparam("ims_registrar_scscf", "subscription_default_expires", UE_SUBSCRIPTION_EXPIRES) +modparam("ims_registrar_scscf", "subscription_min_expires", UE_SUBSCRIPTION_EXPIRES) +modparam("ims_registrar_scscf", "subscription_max_expires", UE_SUBSCRIPTION_EXPIRES) + +# -- CDP params -- +modparam("cdp","config_file","/etc/kamailio_scscf/scscf.xml") + +# -- ims_dialog params -- +modparam("ims_dialog", "dlg_flag", FLT_DIALOG) +modparam("ims_dialog", "timeout_avp", "$avp(DLG_TIMEOUT_AVP)") +modparam("ims_dialog", "detect_spirals", 0) +modparam("ims_dialog", "profiles_no_value", "orig ; term") +#!ifdef DB_URL +#!ifdef DB_URL2 +modparam("ims_dialog", "db_url", "cluster://cluster1") +#!else +modparam("ims_dialog", "db_url", DB_URL) +#!endif +modparam("ims_dialog", "db_mode", 0) +#!endif + +#!ifdef WITH_XMLRPC +# ----- xmlrpc params ----- +modparam("xmlrpc", "route", "XMLRPC"); +modparam("xmlrpc", "url_match", "^/RPC") +#!endif + +#!ifdef WITH_DEBUG +#!ifdef WITH_DEBUG_TRACE +# ----- debugger params ----- +modparam("debugger", "cfgtrace", 1) +#!endif +#!endif + +#!ifdef CAPTURE_NODE +# Destination, where to send the traffic +modparam("siptrace", "duplicate_uri", CAPTURE_NODE) +# Trace all traffic +modparam("siptrace", "trace_on", 1) +modparam("siptrace", "trace_to_database", 0) +modparam("siptrace", "trace_flag", FLT_CAPTURE) +modparam("siptrace", "hep_mode_on", 1) +#!endif + +# -- ims_auth params -- +modparam("ims_auth", "name", URI) +modparam("ims_auth", "registration_default_algorithm", REG_AUTH_DEFAULT_ALG) +#!ifdef CXDX_FORCED_PEER +modparam("ims_auth", "cxdx_forced_peer", CXDX_FORCED_PEER) +#!endif +modparam("ims_auth", "cxdx_dest_realm", EPC_REALM) +modparam("ims_auth", "av_check_only_impu", 1) + +modparam("ims_auth", "max_nonce_reuse", 20) +modparam("ims_auth", "auth_vector_timeout", 60) +modparam("ims_auth", "auth_data_timeout", UE_SUBSCRIPTION_EXPIRES) +modparam("ims_auth", "auth_used_vector_timeout", UE_SUBSCRIPTION_EXPIRES) +modparam("ims_auth", "av_request_at_once", 1) +modparam("ims_auth", "av_request_at_sync", 1) +modparam("ims_auth", "registration_qop", "auth") + +# -- ims_registrar_scscf params -- +#!ifdef WITH_DEBUG +modparam("ims_registrar_scscf", "default_expires", 60) +modparam("ims_registrar_scscf", "min_expires", 60) +modparam("ims_registrar_scscf", "max_expires", 60) +#!else +modparam("ims_registrar_scscf", "default_expires", UE_SUBSCRIPTION_EXPIRES) +modparam("ims_registrar_scscf", "min_expires", UE_SUBSCRIPTION_EXPIRES) +modparam("ims_registrar_scscf", "max_expires", UE_SUBSCRIPTION_EXPIRES) +#!endif +modparam("ims_registrar_scscf", "use_path", 1) +modparam("ims_registrar_scscf", "support_wildcardPSI",1) +modparam("ims_registrar_scscf", "user_data_xsd","/etc/kamailio_scscf/CxDataType_Rel7.xsd") +modparam("ims_registrar_scscf", "scscf_name", URI) +modparam("ims_registrar_scscf", "scscf_name", URI) +modparam("ims_registrar_scscf", "cxdx_dest_realm", EPC_REALM) +modparam("ims_registrar_scscf", "append_branches", 1) +modparam("ims_registrar_scscf", "user_data_always", 0) +modparam("ims_registrar_scscf", "ue_unsubscribe_on_dereg", 1) + +#!ifdef WITH_MULTIDOMAIN +# ----- domain params ----- +#!ifdef DB_URL +#!ifdef DB_URL2 +modparam("domain", "db_url", "cluster://cluster1") +#!else +modparam("domain", "db_url", DB_URL) +#!endif +modparam("domain", "db_mode", 1) +#!endif +# register callback to match myself condition with domains list +modparam("domain", "register_myself", 1) +#!endif + +# ----- ims_isc params ----- +modparam("ims_isc", "my_uri", HOSTNAME) +modparam("ims_isc", "add_p_served_user", 1) + +#!ifdef WITH_RO +# ----- ims_diameter_ro params ----- +#!ifdef DB_URL +#!ifdef DB_URL2 +#modparam("ims_charging", "db_url", "cluster://cluster1") +#!else +#modparam("ims_charging", "db_url", DB_URL) +#!endif +#modparam("ims_charging", "db_mode", 1) +#!endif +modparam("ims_charging", "origin_host", HOSTNAME); +modparam("ims_charging", "origin_realm", NETWORKNAME); +#!ifdef RO_FORCED_PEER +modparam("ims_charging", "ro_forced_peer", RO_FORCED_PEER); +#!endif +modparam("ims_charging", "destination_host", RO_DESTINATION); +modparam("ims_charging", "destination_realm", NETWORKNAME); +modparam("ims_charging", "ro_auth_expiry", UE_SUBSCRIPTION_EXPIRES) + +modparam("ims_charging","service_context_id_root", RO_ROOT); +modparam("ims_charging","service_context_id_ext", RO_EXT); +modparam("ims_charging","service_context_id_mnc", RO_MNC); +modparam("ims_charging","service_context_id_mcc", RO_MCC); +modparam("ims_charging","service_context_id_release", RO_RELEASE); + +modparam("ims_charging","interim_update_credits",30); +modparam("ims_charging","timer_buffer",5); +#!endif + +# ----- enum params ----- +modparam("enum", "domain_suffix", ENUM_SUFFIX) + +# ----- sanity params ----- +modparam("sanity", "autodrop", 0) + +# ----------------- Settings for Dispatcher --------------- +modparam("dispatcher", "list_file", "/etc/kamailio_scscf/dispatcher.list") +# Dispatcher: Enable Failover-Support +modparam("dispatcher", "flags", 2) +# Dispatcher: Overwrite Destination address, if required. +modparam("dispatcher", "force_dst", 1) +# AVP's required for Fail-Over-Support: +#modparam("dispatcher", "dst_avp", "$avp(DISPATCHER_DST_AVP)") +#modparam("dispatcher", "grp_avp", "$avp(DISPATCHER_GRP_AVP)") +#modparam("dispatcher", "cnt_avp", "$avp(DISPATCHER_CNT_AVP)") +#modparam("dispatcher", "sock_avp", "$avp(DISPATCHER_SOCK_AVP)") + +#modparam("dispatcher", "xavp_dst", "$avp(DISPATCHER_DST_AVP)") +#modparam("dispatcher", "xavp_dst_mode", 0) +#modparam("dispatcher", "xavp_ctx", "$avp(DISPATCHER_CNT_AVP)") +#modparam("dispatcher", "xavp_ctx_mode", 0) + +# Try to recover disabled destinations every 15 seconds. +modparam("dispatcher", "ds_ping_interval", 15) +# Actively query the gateways: +modparam("dispatcher", "ds_probing_mode", 1) +modparam("dispatcher", "ds_ping_reply_codes", "class=2;code=404;code=480") + +####### Routing Logic ######## +# Main SIP request routing logic +# - processing of any incoming SIP request starts with this route + +route { +##!ifdef WITH_DEBUG + xnotice("SCSCF: $rm $ru ($fu ($si:$sp) to $tu, $ci)\n"); +##!endif + + # per request initial checks + route(REQINIT); + + # Handle Registrations: + if (is_method("REGISTER")) { + route(REGISTER); + exit; + } + + # we need to support subscription to reg event + if (is_method("SUBSCRIBE") && search("^(Event|o)([ \t]*):([ \t]*)reg")) { + route(SUBSCRIBE); + break; + } + + if (is_method("PUBLISH") && search("^(Event|o)([ \t]*):([ \t]*)reg")) { + route(PUBLISH); + break; + } + + # Evaluate Route-Header and set $route_uri + loose_route(); + + if (is_method("CANCEL|ACK")) { + t_relay(); + exit; + } + + #Set DLG flag to track dialogs using dialog2 + if (!is_method("REGISTER|SUBSCRIBE")) + setflag(FLT_DIALOG); + + if (($route_uri =~ "sip:orig@.*") || ($route_uri =~ "sip:orig@"+HOSTNAME_ESC+".*") || isc_from_as("orig")) { + xlog("Orig"); + # we need something like this to assign SCSCF to unregistered user for services + # support for AS origination on behalf of unregistered useri + # can use the registrar is_registered methods - must see if we need to check orig or term? + + # Sanitize the R-URI if domain is present in from of @MSISDN of caller + # What in case of Roaming? - Need to handle it + # if ($ru =~ ".*phone-context.*") { + # if ($ru =~ "tel:.*") { + # # Handle following request-uri + # # tel:0498765432100;phone-context=ims.mnc001.mcc001.3gppnetwork.org + # $ru = $(ru{re.subst,/tel:/sip:/g}); + # } + # # Now in sip: uri format + # if ($ru =~ ".*@.*") { + # $ru = $(ru{re.subst,/@[0-9+-]*;user=phone/@NETWORKNAME;user=phone/g}); + # #$ru = $(ru{re.subst,/;phone-context=[A-Za-z.0-9+-]*@/;phone-context=NETWORKNAME@/g}); + # } else { + # $ru = $ru + "@" + NETWORKNAME + ";user=phone"; + # #$ru = $(ru{re.subst,/;phone-context=[A-Za-z.0-9+-]*@/;phone-context=NETWORKNAME@/g}); + # } + # } + if (!is_method("REGISTER|SUBSCRIBE")) { + # sip:xxx;phone-context=xxxx@xxx format is not desired + if (($ru =~ ".*phone-context.*") && ($ru =~ "sip:.*")) { + $var(old_ruri) = $ru; + $ru = $(ru{re.subst,/sip:/tel:/g}); + $ru = $(ru{re.subst,/;phone-context=[A-Za-z.0-9+-@]*;user=phone//g}); + $ru = $ru + ";phone-context=" + NETWORKNAME; + msg_apply_changes(); + xnotice("SCSCF: Changed R-URI from $var(old_ruri) to $ru\n"); + } + } + + # Originating + route(orig); + break; + } else { + isc_from_as("term"); + if ($retcode == -2) { + # Treat as originating, since it was retargeted: + route(orig); + break; + } + if ((is_in_profile("orig") || has_totag()) && ($route_uri =~ "sip:mo@"+".*")) { + route(orig_subsequent); + break; + } + if ((is_in_profile("term") || has_totag()) && ($route_uri =~ "sip:mt@"+".*")) { + route(term_subsequent); + break; + } + + # Terminating + if (uri == myself || uri =~ "tel:.*") { + if (!term_impu_registered("location")) { + xlog("L_DBG", "We need to do an UNREG server SAR assignemnt"); + assign_server_unreg("UNREG_SAR_REPLY", "location", "term"); + exit; + } else { + sl_send_reply("403","Forbidden - Domain not served"); + exit(); + } + } + route(term); + break; + } +} + +route[UNREG_SAR_REPLY] +{ + xlog("L_DBG","saa_return code is $avp(s:saa_return_code)\n"); + switch ($avp(s:saa_return_code)){ + case 1: #success + xlog("L_DBG", "SAR success - will route message\n"); + route(term); + break; + case -1: #failure + xlog("L_ERR", "SAR failure - error response sent from module\n"); + break; + case -2: #error + xlog("L_ERR", "SAR error - error response sent from module\n"); + break; + default: + xlog("L_ERR", "Unknown return code from SAR, value is [$avp(s:saa_return_code)]\n"); + break; + } + exit; +} + + +###################################################################### +# Helper routes (Basic-Checks, NAT-Handling/RTP-Control, XML-RPC) +###################################################################### +# Per SIP request initial checks +route[REQINIT] { + $var(used) = 1 - ($stat(free_size) / $stat(total_size)); + xlog("L_DBG", "Mem: Total $stat(total_size), Free $stat(free_size) [$var(used)% used]\n"); + if ($var(used) > 95) { + send_reply("503", "Server overloaded"); + exit; + } + + # Trace this message +#!ifdef CAPTURE_NODE + sip_trace(); + setflag(FLT_CAPTURE); +#!endif + + if (!mf_process_maxfwd_header("10")) { + sl_send_reply("483","Too Many Hops"); + exit; + } + + if(!sanity_check("1511", "7")) { + xlog("Malformed SIP message from $si:$sp\n"); + exit; + } + + # Check for shutdown mode: + if (!has_totag() && ($sel(cfg_get.system.shutdownmode) > 0)) { + send_reply("503", "Server shutting down"); + exit; + } + + # Reply to OPTIONS: + if (is_method("OPTIONS") && (uri==myself)) { + options_reply(); + exit; + } + + # Ignore Re-Transmits: + if (t_lookup_request()) { + exit; + } + if (is_method("INVITE")) { + send_reply("100", "Trying"); + } + +} + + +###################################################################### +# Publish route +###################################################################### +route[PUBLISH] +{ + if (!t_newtran()) { + #absorb retransmissions + sl_reply("500","Could not create transaction"); + exit; + } + + if (can_publish_reg("location")) { + $var(ret)= publish_reg("location"); + switch ($var(ret)){ + case 1: #success + xlog("L_DBG", "Publish reg successful"); + break; + case -1: #failure + xlog("L_ERR", "Publish reg failure - sending 500 Error now\n"); + t_reply("500","Server Error publishing subscription"); + break; + default: + xlog("L_ERR", "Unknown return code from publish reg event alue is [$var(ret)]\n"); + break; + } + } else { + t_reply("403","Forbidden to PUBLISH"); + exit; + } +} + +###################################################################### +# Subscribe route +###################################################################### +route[SUBSCRIBE] +{ + if (!t_newtran()) { + #absorb retransmissions + sl_reply("500","Could not create transaction"); + exit; + } + + if (!has_totag()) { + xlog("L_DBG", "This is an initial SUBSCRIBE\n"); + if (!term_impu_registered("location")) { + xlog("L_DBG", "We need to do an UNREG server SAR assignment\n"); + assign_server_unreg("SUBSCRIBE_UNREG_SAR_REPLY", "location", "term"); + exit; + } + if (!can_subscribe_to_reg("location")) { + t_reply("403","Forbidden to SUBSCRIBE"); + exit; + } + } else { + xlog("L_DBG", "This is a subsequent SUBSCRIBE\n"); + } + + $var(ret)= subscribe_to_reg("location"); + switch ($var(ret)) { + case 1: #success + xlog("L_DBG", "Subscribe to reg successful"); + break; + case -1: #failure + xlog("L_ERR", "Subscribe to reg failure - sending 500 Error now\n"); + t_reply("500","Server Error saving subscription"); + break; + case -2: #error + xlog("L_ERR", "Subscribe to reg error sending notify - 200 OK so subscription already sent\n"); + break; + default: + xlog("L_ERR", "Unknown return code from subscribe to reg event alue is [$var(ret)]\n"); + break; + } +} + +route[SUBSCRIBE_UNREG_SAR_REPLY] +{ + + xlog("L_DBG","saa_return code is $avp(s:saa_return_code)\n"); + switch ($avp(s:saa_return_code)) { + case 1: #success + xlog("L_DBG", "SAR success - will process subscribe\n"); + if (can_subscribe_to_reg("location")) { + $var(ret)= subscribe_to_reg("location"); + switch ($var(ret)) { + case 1: #success + xlog("L_DBG", "Subscribe to reg successful"); + break; + case -1: #failure + xlog("L_ERR", "Subscribe to reg failure - sending 500 Error now\n"); + t_reply("500","Server Error saving subscription"); + break; + case -2: #error + xlog("L_ERR", "Subscribe to reg error sending notify - 200 OK so subscription already sent\n"); + break; + default: + xlog("L_ERR", "Unknown return code from subscribe to reg event alue is [$var(ret)]\n"); + break; + } + } else { + t_reply("403","Forbidden to SUBSCRIBE"); + exit; + } + break; + case -1: #failure + xlog("L_ERR", "SAR failure - Sending 403 Forbidden\n"); + t_reply("403","Forbidden to SUBSCRIBE"); + break; + case -2: #error + xlog("L_ERR", "SAR error - Sending 403 Forbidden\n"); + t_reply("403","Forbidden to SUBSCRIBE"); + break; + default: + xlog("L_ERR", "Unknown return code from SAR, value is [$avp(s:saa_return_code)] - sending 403 Forbidden\n"); + t_reply("403","Forbidden to SUBSCRIBE"); + break; + } + exit; +} + +###################################################################### +# XMLRPC routing +###################################################################### +#!ifdef WITH_XMLRPC +route[XMLRPC] { + if ((method=="POST" || method=="GET") +#!ifdef XMLRPC_WHITELIST_1 +&& ((src_ip == XMLRPC_WHITELIST_1) +#!ifdef XMLRPC_WHITELIST_2 + || (src_ip == XMLRPC_WHITELIST_2) +#!endif +#!ifdef XMLRPC_WHITELIST_3 + || (src_ip == XMLRPC_WHITELIST_3) +#!endif +) +#!endif +) { + # close connection only for xmlrpclib user agents (there is a bug in + # xmlrpclib: it waits for EOF before interpreting the response). + if ($hdr(User-Agent) =~ "xmlrpclib") + set_reply_close(); + set_reply_no_connect(); + dispatch_rpc(); + exit; + } + send_reply("403", "Forbidden"); + exit; +} +#!endif + +###################################################################### +# Route for handling Registrations: +###################################################################### +route[REGISTER] { + xnotice("ALGORITHM IS [$aa] and User-Agent is [$ua]\n"); + $avp(alg) = $aa; + if ($aa == $null) { + $avp(alg) = "MD5"; #force to MD5 for zoiper.... non-ims + } +#!ifdef WITH_AUTH + if (!ims_www_authenticate("$td")) { +#!else + if (($avp(alg) == "MD5") && (!ims_www_authenticate("$td"))) { +#!endif + if ($? == -2) { + send_reply("403", "Authentication Failed"); + exit; + } else if ($? == -3) { + send_reply("400", "Bad Request"); + exit; + } else if ($? == -9) { + xlog("L_DBG", "Authentication re-sync requested\n"); + ims_www_resync_auth("REG_RESYNC_REPLY", "$td"); + exit; + } else { + #user has not been authenticated. Lets send a challenge via 401 Unauthorized + xlog("L_DBG","About to challenge! auth_ims[$avp(alg)]\n"); + ims_www_challenge("REG_MAR_REPLY", "$td", "$avp(alg)"); + exit; + } + } else { + xlog("L_DBG", "Auth succeeded\n"); + # We need to check if this user is registered or not + if (!impu_registered("location")) { + xlog("L_ERR", "Not REGISTERED\n"); + save("PRE_REG_SAR_REPLY","location"); + exit; + } else { + isc_match_filter_reg("1","location"); + save("REG_SAR_REPLY","location"); + exit; + } + } +} + +route[REG_MAR_REPLY] +{ + #this is async so to know status we have to check the reply avp + xlog("L_DBG","maa_return code is $avp(s:maa_return_code)\n"); + + switch ($avp(s:maa_return_code)) { + case 1: #success + xlog("L_DBG", "MAR success - 401/407 response sent from module\n"); + break; + case -1: #failure + xlog("L_ERR", "MAR failure - error response sent from module\n"); + break; + case -2: #error + xlog("L_ERR", "MAR error - sending error response now\n"); + send_reply("500", "MAR failed"); + break; + default: + xlog("L_ERR", "Unknown return code from MAR, value is [$avp(s:maa_return_code)]\n"); + send_reply("500", "Unknown response code from MAR"); + break; + } + exit; +} + +route[PRE_REG_SAR_REPLY] +{ + xlog("L_DBG","saa_return code is $avp(s:saa_return_code)\n"); + #this is async so to know status we have to check the reply avp + xlog("L_DBG","saa_return code (for scscf_save on register) is $avp(s:saa_return_code)\n"); + switch ($avp(s:saa_return_code)) { + case 1: #success + xlog("L_DBG", "SAR success - 200 response sent from module\n"); + isc_match_filter_reg("0","location"); + exit; + case -1: #failure + xlog("L_ERR", "SAR failure - error response sent from module\n"); + break; + case -2: #error + xlog("L_ERR", "SAR error - error response sent from module\n"); + break; + default: + xlog("L_ERR", "Unknown return code from SAR, value is [$avp(s:saa_return_code)]\n"); + break; + } + exit; +} + +route[REG_SAR_REPLY] +{ + xlog("L_DBG","saa_return code is $avp(s:saa_return_code)\n"); + #this is async so to know status we have to check the reply avp + xlog("L_DBG","saa_return code (for scscf_save on register) is $avp(s:saa_return_code)\n"); + switch ($avp(s:saa_return_code)) { + case 1: #success + xlog("L_DBG", "SAR success - 200 response sent from module\n"); + exit; + case -1: #failure + xlog("L_ERR", "SAR failure - error response sent from module\n"); + break; + case -2: #error + xlog("L_ERR", "SAR error - error response sent from module\n"); + break; + default: + xlog("L_ERR", "Unknown return code from SAR, value is [$avp(s:saa_return_code)]\n"); + break; + } + exit; +} + +route[REG_RESYNC_REPLY] +{ + xdbg("ALGORITHM was [$aa] and now [$avp(alg)]\n"); + ims_www_challenge("REG_MAR_REPLY", "$td", "$avp(alg)"); +} + +###################################################################### +# Apply privacy, if requested +###################################################################### +route[apply_privacy] +{ + if (is_present_hf("Privacy") && ($hdr(Privacy)=="id")) { + remove_hf("P-Asserted-Identity"); + } +} + +###################################################################### +# Originating, Intial Requests +###################################################################### +route[orig] +{ + xlog("L_DBG","Enter orig route\n"); + set_dlg_profile("orig"); + + # we MAYBE need something like this to check if a user is barred + # if (S_originating_barred()){ + # sl_send_reply("403","Forbidden - Originating Public Identity barred"); + # exit; + # } + + if (is_method("INVITE|SUBSCRIBE")) { + $avp(RR_CUSTOM_USER_AVP)="mo"; + record_route(); + } + + # Start new transaction: + t_newtran(); + + # check if dialog saved as fwded to AS + if (isc_match_filter("orig", "location")) { + t_on_failure("isc_orig_failure"); + xlog("Orig - msg was fwded to AS\n"); + exit; + } + + if (!isc_from_as("orig")) { + remove_hf("P-Asserted-Identity"); + append_hf("P-Asserted-Identity: \r\n"); + } + +#!ifdef WITH_RO + # before we allow call - lets check credit + if (is_method("INVITE")) { + xlog("L_DBG","Sending initial CCR Request for call\n"); + $var(cc_ret) = Ro_CCR("CHARGING_CCR_ORIG_REPLY", "orig", 30, "0", "0"); + if ($var(cc_ret) < 0) { + xlog("L_ERR","CCR Request failure\n"); + sl_send_reply("402","Payment required"); + exit; + } + xlog("L_DBG","CCR Request success\n"); + exit; + } +#!endif + route(FINAL_ORIG); +} + +route[FINAL_ORIG] +{ + # Check for PSTN destinations: + if (is_method("INVITE")) { + route(PSTN_handling); + } + + t_on_reply("orig_reply"); + + t_relay(); +} + +route[CHARGING_CCR_ORIG_REPLY] +{ + xlog("L_DBG","cca_return code is $avp(s:cca_return_code)\n"); + + switch ($avp(s:cca_return_code)) { + case 1: #success + xlog("L_DBG", "CCR success - will route message\n"); + route(FINAL_ORIG); + break; + case -1: #failure + xlog("L_ERR", "CCR failure - error response sent from module\n"); + switch ($avp(s:cca_result_code)) { + case 5030: + send_reply("403", "Charging User not found"); + break; + case 5031: + send_reply("403", "Rating failed"); + break; + case 4010: + send_reply("402", "Payment required - Unsufficient funds"); + break; + case 5006: + send_reply("486", "Line limit exceeded"); + break; + default: + send_reply("402","Payment required ($avp(s:cca_result_code))"); + break; + } + case -2: #error + xlog("L_ERR", "CCR error - error response sent from module\n"); + send_reply("500", "Charging Error"); + break; + default: + xlog("L_ERR", "Unknown return code from CCR: [$avp(s:cca_return_code)] \n"); + send_reply("500", "Charging Error"); + break; + } + exit; +} + + +###################################################################### +# Replies to the Initial Requests +###################################################################### +onreply_route[orig_reply] +{ + xlog("L_DBG","Orig reply\n"); + + route(apply_privacy); + break; +} + +###################################################################### +# Originating, subsequent requests +###################################################################### +route[orig_subsequent] +{ + xlog("L_DBG","Orig_Subsequent\n"); + + if (!is_method("ACK")) { + t_on_reply("orig_subsequent_reply"); + } + t_relay(); +} + +###################################################################### +# Replies for originating, subsequent requests +###################################################################### +onreply_route[orig_subsequent_reply] +{ + xlog("L_DBG","Orig_Subsequent_reply\n"); + route(apply_privacy); + break; +} + +###################################################################### +# Failure-Route for Requests to an AS +###################################################################### +failure_route[isc_orig_failure] +{ + xlog("L_DBG","ISC_Orig_failure\n"); + + if (t_check_status("(408)|(5..)")){ + t_on_failure("isc_orig_failure"); + if (isc_match_filter("orig","location")){ + xlog("L_DBG","ISC_Orig_failure - msg was fwded to AS\n"); + exit; + } + + if (isc_from_as("origfail")) { + remove_hf("P-Asserted-Identity"); + append_hf("P-Asserted-Identity: \r\n"); + } + + t_on_reply("orig_reply"); + + t_relay(); + } +} + +###################################################################### +# Terminating requests +###################################################################### +route[term] +{ + xlog("L_DBG","Term\n"); + + set_dlg_profile("term"); + + #we need something like this to check if a user is barred + # if (S_terminating_barred()){ + # sl_send_reply("404","Not Found - Terminating user barred"); + # exit; + # } + + if (is_method("INVITE|SUBSCRIBE")) { + $avp(RR_CUSTOM_USER_AVP)="mt"; + $avp(i:20)="mt"; + record_route(); + } + + # check if dialog saved as fwded to AS + if (isc_match_filter("term","location")){ + t_on_failure("isc_term_failure"); + xlog("L_DBG","Term - msg was fwded to AS\n"); + exit; + } + +#!ifdef WITH_RO_TERM + # before we allow call - lets check credit + if (is_method("INVITE")) { + xlog("L_DBG","Sending initial CCR Request for call\n"); + $var(cc_ret) = Ro_CCR("CHARGING_CCR_TERM_REPLY", "term", 30, "0", "0"); + if ($var(cc_ret) < 0) { + xlog("L_ERR","CCR Request failure\n"); + sl_send_reply("402","Payment required"); + exit; + } + xlog("L_DBG","CCR Request success\n"); + exit; + } +#!endif + route(FINAL_TERM); +} + +route[FINAL_TERM] { + if (lookup("location")) { + if (uri==myself) { + if (!t_newtran()) { + sl_reply_error(); + exit; + } + t_reply("404","Not Found - destination user not found on this S-CSCF"); + exit; + } + } else { + # User not registered? Reply with 404. + if (!t_newtran()) { + sl_reply_error(); + exit; + } + t_reply("404","Not Found - destination user not found on this S-CSCF"); + exit; + } + route(apply_privacy); + + t_relay(); +} + + +route[CHARGING_CCR_TERM_REPLY] +{ + xlog("L_DBG","cca_return code is $avp(s:cca_return_code)\n"); + + switch ($avp(s:cca_return_code)) { + case 1: #success + xlog("L_DBG", "CCR success - will route message\n"); + route(FINAL_TERM); + break; + case -1: #failure + xlog("L_ERR", "CCR failure - error response sent from module\n"); + switch ($avp(s:cca_result_code)) { + case 5030: + send_reply("403", "Charging User not found"); + break; + case 5031: + send_reply("403", "Rating failed"); + break; + case 4010: + send_reply("402", "Payment required - Unsufficient funds"); + break; + case 5006: + send_reply("486", "Line limit exceeded"); + break; + default: + send_reply("402","Payment required ($avp(s:cca_result_code))"); + break; + } + case -2: #error + xlog("L_ERR", "CCR error - error response sent from module\n"); + send_reply("500", "Charging Error"); + break; + default: + xlog("L_ERR", "Unknown return code from CCR: [$avp(s:cca_return_code)] \n"); + send_reply("500", "Charging Error"); + break; + } + exit; +} + + +###################################################################### +# Failure Route for Terminating requests +###################################################################### +failure_route[isc_term_failure] +{ + xlog("L_DBG","ISC_term_failure\n"); + + if (t_check_status("(408)|(5..)")){ + t_on_failure("isc_term_failure"); + if (isc_match_filter("term","location")){ + xlog("L_DBG","Term - msg was fwded to AS\n"); + exit; + } + + if (lookup("location")) { + if (uri==myself) { + t_reply("404","Not Found - destination user not found on this S-CSCF"); + exit; + } + } else { + t_reply("404","Not Found - destination user not found on this S-CSCF"); + exit; + } + t_relay(); + } +} + +###################################################################### +# Terminating, subsequent requests +###################################################################### +route[term_subsequent] +{ + xlog("L_DBG","term_subsequent\n"); + route(apply_privacy); + t_relay(); +} + +###################################################################### +# Check for PSTN destinations: +###################################################################### +route[PSTN_handling] +{ + # First, we translate "tel:"-URI's to SIP-URI's: + # $ru: tel:+(34)-999-888-777 + # $fu: sip:test@foo.com + # becomes $ru: sip:+34999888777@foo.com;user=phone + if (tel2sip2("$ru", "$fd", "$ru") < 0) + xlog("L_WARN","Failed to convert $ru to a sip:-URI - M=$rm R=$ru F=$fu T=$tu IP=$si:$sp ID=$ci\n\n"); + + if ($rU =~ "\+[0-9]+") { + # Now let's check, if the number can be found in ENUM: + if(!enum_query()) { + # ENUM failed, send it to the PSTN-Gateway: + route(PSTN); + break; + } + } +} + +###################################################################### +# Send calls to the PSTN-Gateways: +###################################################################### +route[PSTN] +{ + $var(has_trf) = 0; + if (is_present_hf("Feature-Caps")) { + xlog("Feature-Caps: $hdr(Feature-Caps) => $(hdr(Feature-Caps){param.value,+g.3gpp.trf}{nameaddr.uri}{uri.host})\n"); + if ($(hdr(Feature-Caps){param.value,+g.3gpp.trf}) != $null) { + $rd = $(hdr(Feature-Caps){param.value,+g.3gpp.trf}{nameaddr.uri}{uri.host}); + if (!strempty($(ou{uri.params}))) { + $ru = $ru+";"+$(ou{uri.params}); + } + + t_on_failure("TRF_failure"); + if (t_relay_to("0x02")) { + $var(has_trf) = 1; + } else { + xlog("Relay to $du failed.\n"); + $du = $null; + } + } + } + + if ($var(has_trf) == 0) { + if (!ds_select_domain("1", "4")) { + xlog("L_WARN","No PSTN-Gateways available - M=$rm R=$ru F=$fu T=$tu IP=$si:$sp ID=$ci\n\n"); + send_reply("503", "Service not available"); + exit; + } + if (!strempty($(ou{uri.params}))) { + $ru = $ru+";"+$(ou{uri.params}); + } + t_relay(); + } + # Relay the request: + t_on_failure("PSTN_failure"); + + exit; +} + +###################################################################### +# manage failure routing cases, perform failover +###################################################################### +failure_route[TRF_failure] { + xlog("TRF_failure\n"); + # Choose another gateway, in case we + # - get a local generated "408" + # - receive a 5xx or 6xx reply from the proxy. + if (t_branch_timeout() || t_check_status("[5-6]..")) { + $du = $null; + if (!ds_select_domain("1", "4")) { + xlog("L_WARN","No PSTN-Gateways available - M=$rm R=$ru F=$fu T=$tu IP=$si:$sp ID=$ci\n\n"); + send_reply("503", "Service not available"); + exit; + } + if (!strempty($(ou{uri.params}))) { + $ru = $ru+";"+$(ou{uri.params}); + } + # Relay the request: + t_on_failure("PSTN_failure"); + + t_relay(); + exit; + } +} + +###################################################################### +# manage failure routing cases, perform failover +###################################################################### +failure_route[PSTN_failure] { + # Choose another gateway, in case we + # - get a local generated "408" + # - receive a 5xx or 6xx reply from the proxy. + if (t_branch_timeout() || t_check_status("[5-6]..")) { + if (ds_next_domain()) { + if (!strempty($(ou{uri.params}))) { + $ru = $ru+";"+$(ou{uri.params}); + } + # Do Failover in case problems: + t_on_failure("PSTN_failure"); + t_relay(); + } else { + # Add a header, to indicate the phone should try again in 30 seconds. + append_hf("Retry-After: 30\r\n"); + send_reply("503", "Service not available"); + } + exit; + } +} diff --git a/custom_deployments/open5gs_hss_cx/scscf/scscf.cfg b/custom_deployments/open5gs_hss_cx/scscf/scscf.cfg new file mode 100644 index 0000000..4440519 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/scscf/scscf.cfg @@ -0,0 +1,89 @@ +# SIP / UDP +listen=udp:SCSCF_IP:6060 +# SIP / TCP +listen=tcp:SCSCF_IP:6060 +# SIP / TCP/TLS +#listen=tls:SCSCF_IP:6061 + +#!define NETWORKNAME "IMS_DOMAIN" +#!define EPC_REALM "EPC_DOMAIN" +#!define NETWORKNAME_ESC "IMS_SLASH_DOMAIN" +#!define HOSTNAME "scscf.IMS_DOMAIN" +#!define HOSTNAME_ESC "scscf\.IMS_SLASH_DOMAIN" +#!define URI "sip:scscf.IMS_DOMAIN:6060" + +#!subst "/NETWORKNAME/IMS_DOMAIN/" + +alias=scscf.IMS_DOMAIN + +# ENUM-Server to query: +#!define ENUM_SUFFIX "e164.arpa." + +# SIP-Address of capturing node, if not set, capturing is disabled. +##!define CAPTURE_NODE "sip:127.0.0.1:9060" + +# Connection URL for the database: +# For use with a single database: +#!define DB_URL "mysql://scscf:heslo@MYSQL_IP/scscf" + +# For use with DB_Cluster: con1 (primary), con2 (backup) +##!define DB_URL "con1=>mysql://scscf:heslo@MYSQL_IP/scscf" +##!define DB_URL2 "con2=>mysql://scscf:heslo@MYSQL_IP/scscf" + +# Select Authorization Algorhithm: +##!define REG_AUTH_DEFAULT_ALG "AKAv1-MD5" +##!define REG_AUTH_DEFAULT_ALG "AKAv2-MD5" +##!define REG_AUTH_DEFAULT_ALG "MD5" +##!define REG_AUTH_DEFAULT_ALG "CableLabs-Digest" +##!define REG_AUTH_DEFAULT_ALG "3GPP-Digest" +##!define REG_AUTH_DEFAULT_ALG "TISPAN-HTTP_DIGEST_MD5" +# Let the HSS decide +#!define REG_AUTH_DEFAULT_ALG "HSS-Selected" + +# Number of TCP Processes +#!define TCP_PROCESSES 3 + +# Maximum lifetime of a subscription in seconds (same is advertised to UE) +#!substdef "/UE_SUBSCRIPTION_EXPIRES/SUBSCRIPTION_EXPIRES_ENV/g" + +##!define RO_FORCED_PEER "32260@3gpp.org" +#!define RO_DESTINATION "hssocs.voiceblue.com" +#!define RO_ROOT "32260@3gpp.org" +#!define RO_EXT "ext" +#!define RO_MNC "02" +#!define RO_MCC "001" +#(see https://en.wikipedia.org/wiki/Mobile_country_code_(MCC)) +#!define RO_RELEASE "8" +# See http://tools.ietf.org/html/rfc4006#section-4.1.2 for the definition of the Service-Context + +##!define XMLRPC_WHITELIST_1 "127.0.0.1" +##!define XMLRPC_WHITELIST_2 "127.0.0.1" +##!define XMLRPC_WHITELIST_3 "127.0.0.1" + +# Several features can be enabled using '#!define WITH_FEATURE' directives: +# +# *** To run in debug mode: +# - define WITH_DEBUG +# +# *** To enable TCP support execute: +# - define WITH_TCP +# +# *** To enable XMLRPC support execute: +# - define WITH_XMLRPC +# - this will automagically enable TCP +# +# *** To enable the Ro-Interface: +# - Configure Ro-Diameter-Interface in scscf.xml +# - define WITH_RO +# +# *** To enable a Homer SIP-Capter-Node: +# - define CAPTURE_NODE with a proper address +# +# Enabled Features for this host: +##!define WITH_DEBUG +##!define WITH_DEBUG_TRACE +#!define WITH_TCP +##!define WITH_XMLRPC +##!define WITH_RO +##!define WITH_RO_TERM +#!define WITH_AUTH diff --git a/custom_deployments/open5gs_hss_cx/scscf/scscf.xml b/custom_deployments/open5gs_hss_cx/scscf/scscf.xml new file mode 100644 index 0000000..f12043b --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/scscf/scscf.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + diff --git a/custom_deployments/open5gs_hss_cx/scscf/scscf_init.sh b/custom_deployments/open5gs_hss_cx/scscf/scscf_init.sh new file mode 100755 index 0000000..8f89c64 --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/scscf/scscf_init.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +mkdir -p /etc/kamailio_scscf +cp /mnt/scscf/scscf.cfg /etc/kamailio_scscf +cp /mnt/scscf/scscf.xml /etc/kamailio_scscf +cp /mnt/scscf/kamailio_scscf.cfg /etc/kamailio_scscf +cp /mnt/scscf/CxDataType_Rel6.xsd /etc/kamailio_scscf +cp /mnt/scscf/CxDataType_Rel7.xsd /etc/kamailio_scscf +cp /mnt/scscf/CxDataType_Rel8.xsd /etc/kamailio_scscf +cp /mnt/scscf/dispatcher.list /etc/kamailio_scscf + +while ! mysqladmin ping -h ${MYSQL_IP} --silent; do + sleep 5; +done + +# Sleep until permissions are set +sleep 10; + +# Create SCSCF database, populate tables and grant privileges +if [[ -z "`mysql -u root -h ${MYSQL_IP} -qfsBe "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='scscf'" 2>&1`" ]]; +then + mysql -u root -h ${MYSQL_IP} -e "create database scscf;" + mysql -u root -h ${MYSQL_IP} scscf < /usr/local/src/kamailio/utils/kamctl/mysql/standard-create.sql + mysql -u root -h ${MYSQL_IP} scscf < /usr/local/src/kamailio/utils/kamctl/mysql/presence-create.sql + mysql -u root -h ${MYSQL_IP} scscf < /usr/local/src/kamailio/utils/kamctl/mysql/ims_usrloc_scscf-create.sql + mysql -u root -h ${MYSQL_IP} scscf < /usr/local/src/kamailio/utils/kamctl/mysql/ims_dialog-create.sql + mysql -u root -h ${MYSQL_IP} scscf < /usr/local/src/kamailio/utils/kamctl/mysql/ims_charging-create.sql + SCSCF_USER_EXISTS=`mysql -u root -h ${MYSQL_IP} -s -N -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE User = 'scscf' AND Host = '%')"` + if [[ "$SCSCF_USER_EXISTS" == 0 ]] + then + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'scscf'@'%' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'scscf'@'$SCSCF_IP' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON scscf.* TO 'scscf'@'%'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON scscf.* TO 'scscf'@'$SCSCF_IP'"; + mysql -u root -h ${MYSQL_IP} -e "FLUSH PRIVILEGES;" + fi +fi + +export IMS_SLASH_DOMAIN=`echo $IMS_DOMAIN | sed 's/\./\\\./g'` + +SUBSCRIPTION_EXPIRES_ENV=3600 + +sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' /etc/kamailio_scscf/scscf.cfg +sed -i 's|SUBSCRIPTION_EXPIRES_ENV|'$SUBSCRIPTION_EXPIRES_ENV'|g' /etc/kamailio_scscf/scscf.cfg +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/kamailio_scscf/scscf.cfg +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/kamailio_scscf/scscf.cfg +sed -i 's|IMS_SLASH_DOMAIN|'$IMS_SLASH_DOMAIN'|g' /etc/kamailio_scscf/scscf.cfg +sed -i 's|MYSQL_IP|'$MYSQL_IP'|g' /etc/kamailio_scscf/scscf.cfg + +sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' /etc/kamailio_scscf/scscf.xml +sed -i 's|SUBSCRIPTION_EXPIRES_ENV|'$SUBSCRIPTION_EXPIRES_ENV'|g' /etc/kamailio_scscf/scscf.xml +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/kamailio_scscf/scscf.xml +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/kamailio_scscf/scscf.xml +sed -i 's|HSS_BIND_PORT|'$HSS_BIND_PORT'|g' /etc/kamailio_scscf/scscf.xml +sed -i 's|SCSCF_BIND_PORT|'$SCSCF_BIND_PORT'|g' /etc/kamailio_scscf/scscf.xml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/open5gs_hss_cx/srsenb.yaml b/custom_deployments/open5gs_hss_cx/srsenb.yaml new file mode 100644 index 0000000..e4d264b --- /dev/null +++ b/custom_deployments/open5gs_hss_cx/srsenb.yaml @@ -0,0 +1,30 @@ +version: '3' +services: + srsenb: + image: docker_srslte + container_name: srsenb + stdin_open: true + tty: true + privileged: true + devices: + - "/dev/bus" + volumes: + - /dev/serial:/dev/serial:ro + - /dev/bus/usb:/dev/bus/usb:ro + - ../../srslte:/mnt/srslte + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=enb + expose: + - "36412/sctp" + - "2152/udp" + networks: + default: + ipv4_address: ${SRS_ENB_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/custom_deployments/slicing/.custom_env b/custom_deployments/slicing/.custom_env new file mode 100644 index 0000000..d5f188d --- /dev/null +++ b/custom_deployments/slicing/.custom_env @@ -0,0 +1,169 @@ +# Set proper timezone to sync times between docker host and containers +#TZ=Europe/Berlin + +MCC=001 +MNC=01 +TAC=1 + +TEST_NETWORK=172.22.0.0/24 +DOCKER_HOST_IP=192.168.1.223 + +# MONGODB +MONGO_IP=172.22.0.2 + +# HSS - open5gs +HSS_IP=172.22.0.3 + +# PCRF +PCRF_IP=172.22.0.4 +PCRF_BIND_PORT=3873 + +# SGW +SGWC_IP=172.22.0.5 +SGWU_IP=172.22.0.6 +SGWU_ADVERTISE_IP=172.22.0.6 + +# SMF +SMF_IP=172.22.0.7 +SMF_DNS1=8.8.8.8 +SMF_DNS2=8.8.4.4 +SMF2_IP=172.22.0.100 + +# UPF +UPF_IP=172.22.0.8 +UPF_ADVERTISE_IP=172.22.0.8 +UPF2_IP=172.22.0.90 +UPF2_ADVERTISE_IP=172.22.0.90 +# Allowed values for UPF_TUNTAP_MODE are 'tun' or 'tap' +# If 'tap' is used as IF mode, then UPF_INTERNET_APN_IF_NAME and UPF_IMS_APN_IF_NAME must contain string 'tap' +UPF_TUNTAP_MODE=tun +# If 'tap' is used as IF mode, then UPF2_PRIVATE_APN_IF_NAME must contain string 'tap' +UPF2_TUNTAP_MODE=tun +UPF_INTERNET_APN_IF_NAME=ogstun +UPF_IMS_APN_IF_NAME=ogstun2 +UPF2_PRIVATE_APN_IF_NAME=ogstun + +# MME +MME_IP=172.22.0.9 + +# AMF +AMF_IP=172.22.0.10 + +# AUSF +AUSF_IP=172.22.0.11 + +# NRF +NRF_IP=172.22.0.12 + +# UDM +UDM_IP=172.22.0.13 + +# UDR +UDR_IP=172.22.0.14 + +# IMS DNS +DNS_IP=172.22.0.15 + +# RTPENGINE +RTPENGINE_IP=172.22.0.16 + +# MYSQL +MYSQL_IP=172.22.0.17 + +# PYHSS +PYHSS_IP=172.22.0.18 +PYHSS_BIND_PORT=3875 + +# ICSCF +ICSCF_IP=172.22.0.19 +ICSCF_BIND_PORT=3869 + +# SCSCF +SCSCF_IP=172.22.0.20 +SCSCF_BIND_PORT=3870 + +# PCSCF +PCSCF_IP=172.22.0.21 +PCSCF_BIND_PORT=3871 + +# SRSLTE ENB +SRS_ENB_IP=172.22.0.22 + +# UERANSIM +NR_GNB_IP=172.22.0.23 +NR_UE_IP=172.22.0.24 +NR_UE2_IP=172.22.0.91 + +UE1_IMEI=356938035643803 +UE1_IMEISV=4370816125816151 +UE1_IMSI=001011224567895 +UE1_KI=8baf473f2f8fd09487cccbd7097c6862 +UE1_OP=11111111111111111111111111111111 +UE1_AMF=8000 + +UE2_IMEI=356938035643804 +UE2_IMEISV=4370816125816152 +UE2_IMSI=001011224567896 +UE2_KI=8baf473f2f8fd09487cccbd7097c6862 +UE2_OP=11111111111111111111111111111111 +UE2_AMF=8000 + +# OAI ENB +OAI_ENB_IP=172.22.0.25 + +# OPEN5GS WEBUI +WEBUI_IP=172.22.0.26 + +# PCF +PCF_IP=172.22.0.27 + +# NSSF +NSSF_IP=172.22.0.28 + +# BSF +BSF_IP=172.22.0.29 + +# ENTITLEMENT SERVER +ENTITLEMENT_SERVER_IP=172.22.0.30 + +# OSMOMSC +OSMOMSC_IP=172.22.0.31 + +# OSMOHLR +OSMOHLR_IP=172.22.0.32 + +# SMSC +SMSC_IP=172.22.0.33 + +# SRSLTE UE +SRS_UE_IP=172.22.0.34 + +# SCP +SCP_IP=172.22.0.35 + +# METRICS +METRICS_IP=172.22.0.36 + +# SRSRAN GNB +SRS_GNB_IP=172.22.0.37 + +# GRAFANA +GRAFANA_IP=172.22.0.39 +GRAFANA_USERNAME=open5gs +GRAFANA_PASSWORD=open5gs + +# OCS +OCS_IP=172.22.0.40 +OCS_BIND_PORT=3872 + +# UE IPv4 Subnet Range for APN=internet +UE_IPV4_INTERNET=192.168.100.0/24 + +# UE IPv4 Subnet Range for APN=ims +UE_IPV4_IMS=192.168.101.0/24 + +# UE IPv4 Subnet Range for APN=private +UE_IPV4_PRIVATE=192.168.101.0/24 + +# Maximum Number of UEs +MAX_NUM_UE=1024 diff --git a/custom_deployments/slicing/README.md b/custom_deployments/slicing/README.md new file mode 100644 index 0000000..4755b75 --- /dev/null +++ b/custom_deployments/slicing/README.md @@ -0,0 +1,45 @@ +## Deployment description + +This custom deployment showcases a slicing scenario by deploying two instances of open5gs SMF and UPF each handling an individual slice configuration. + +## Additional steps + +Most of the steps to be followed are similar to the steps mentioned in the [README in the root folder](../../README.md). However, additional steps mentioned below must be taken into account while deploying this custom deployment scenario. + +### Loading environmental variables for custom deployment + +**Warning** +For custom deployments, you must modify/use only the [**.custom_env**](.custom_env) file rather than the [**.env** in the root folder](../../.env). + +``` +set -a +source .custom_env +set +a +``` + +### Scenario deployment + +Deploy the 5G SA network consisting of two slices. + +``` +cd custom_deployments/slicing +docker compose -f sa-deploy.yaml up +``` + +Deploy UERANSIM gNB (RF simulated). + +``` +docker compose -f nr-gnb.yaml up -d && docker container attach nr_gnb +``` + +Deploy UERANSIM NR-UE (RF simulated) for first slice. + +``` +docker compose -f nr-ue.yaml up -d && docker container attach nr_ue +``` + +Deploy UERANSIM NR-UE (RF simulated) for second slice. + +``` +docker compose -f nr-ue2.yaml up -d && docker container attach nr_ue2 +``` diff --git a/custom_deployments/slicing/amf/amf.yaml b/custom_deployments/slicing/amf/amf.yaml new file mode 100644 index 0000000..bd8182a --- /dev/null +++ b/custom_deployments/slicing/amf/amf.yaml @@ -0,0 +1,62 @@ +logger: + file: + path: /open5gs/install/var/log/open5gs/amf.log + +sbi: + server: + no_tls: true + client: + no_tls: true + +global: + max: + ue: MAX_NUM_UE + +amf: + sbi: + server: + - address: AMF_IP + port: 7777 + client: + nrf: + - uri: http://NRF_IP:7777 + scp: + - uri: http://SCP_IP:7777 + ngap: + server: + - address: AMF_IP + guami: + - plmn_id: + mcc: MCC + mnc: MNC + amf_id: + region: 2 + set: 1 + tai: + - plmn_id: + mcc: MCC + mnc: MNC + tac: TAC + plmn_support: + - plmn_id: + mcc: MCC + mnc: MNC + s_nssai: + - sst: 1 + sd: 000001 + - sst: 1 + sd: 000002 + security: + integrity_order : [ NIA2, NIA1, NIA0 ] + ciphering_order : [ NEA0, NEA1, NEA2 ] + network_name: + full: Open5GS + amf_name: open5gs-amf0 + metrics: + server: + - address: AMF_IP + port: 9091 + time: + t3512: + value: 540 + diff --git a/custom_deployments/slicing/amf/amf_init.sh b/custom_deployments/slicing/amf/amf_init.sh new file mode 100755 index 0000000..47a928a --- /dev/null +++ b/custom_deployments/slicing/amf/amf_init.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +cp /mnt/amf/amf.yaml install/etc/open5gs +sed -i 's|AMF_IP|'$AMF_IP'|g' install/etc/open5gs/amf.yaml +sed -i 's|SCP_IP|'$SCP_IP'|g' install/etc/open5gs/amf.yaml +sed -i 's|NRF_IP|'$NRF_IP'|g' install/etc/open5gs/amf.yaml +sed -i 's|MNC|'$MNC'|g' install/etc/open5gs/amf.yaml +sed -i 's|MCC|'$MCC'|g' install/etc/open5gs/amf.yaml +sed -i 's|TAC|'$TAC'|g' install/etc/open5gs/amf.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/amf.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/slicing/nr-gnb.yaml b/custom_deployments/slicing/nr-gnb.yaml new file mode 100644 index 0000000..72a1723 --- /dev/null +++ b/custom_deployments/slicing/nr-gnb.yaml @@ -0,0 +1,29 @@ +version: '3' +services: + nr_gnb: + image: docker_ueransim + container_name: nr_gnb + stdin_open: true + tty: true + volumes: + - ./ueransim:/mnt/ueransim + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=ueransim-gnb + expose: + - "38412/sctp" + - "2152/udp" + - "4997/udp" + cap_add: + - NET_ADMIN + privileged: true + networks: + default: + ipv4_address: ${NR_GNB_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/custom_deployments/slicing/nr-ue.yaml b/custom_deployments/slicing/nr-ue.yaml new file mode 100644 index 0000000..1a99017 --- /dev/null +++ b/custom_deployments/slicing/nr-ue.yaml @@ -0,0 +1,27 @@ +version: '3' +services: + nr_ue: + image: docker_ueransim + container_name: nr_ue + stdin_open: true + tty: true + volumes: + - ./ueransim:/mnt/ueransim + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=ueransim-ue + expose: + - "4997/udp" + cap_add: + - NET_ADMIN + privileged: true + networks: + default: + ipv4_address: ${NR_UE_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/custom_deployments/slicing/nr-ue2.yaml b/custom_deployments/slicing/nr-ue2.yaml new file mode 100644 index 0000000..0d412f1 --- /dev/null +++ b/custom_deployments/slicing/nr-ue2.yaml @@ -0,0 +1,27 @@ +version: '3' +services: + nr_ue2: + image: docker_ueransim + container_name: nr_ue2 + stdin_open: true + tty: true + volumes: + - ./ueransim:/mnt/ueransim + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=ueransim-ue2 + expose: + - "4997/udp" + cap_add: + - NET_ADMIN + privileged: true + networks: + default: + ipv4_address: ${NR_UE2_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/custom_deployments/slicing/nssf/nssf.yaml b/custom_deployments/slicing/nssf/nssf.yaml new file mode 100644 index 0000000..1c40f81 --- /dev/null +++ b/custom_deployments/slicing/nssf/nssf.yaml @@ -0,0 +1,34 @@ +logger: + file: + path: /open5gs/install/var/log/open5gs/nssf.log + +sbi: + server: + no_tls: true + client: + no_tls: true + +global: + max: + ue: MAX_NUM_UE + +nssf: + sbi: + server: + - address: NSSF_IP + port: 7777 + client: + nrf: + - uri: http://NRF_IP:7777 + scp: + - uri: http://SCP_IP:7777 + nsi: + - uri: http://NRF_IP:7777 + s_nssai: + sst: 1 + sd: 000001 + - uri: http://NRF_IP:7777 + s_nssai: + sst: 1 + sd: 000002 + diff --git a/custom_deployments/slicing/nssf/nssf_init.sh b/custom_deployments/slicing/nssf/nssf_init.sh new file mode 100755 index 0000000..3417de4 --- /dev/null +++ b/custom_deployments/slicing/nssf/nssf_init.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +cp /mnt/nssf/nssf.yaml install/etc/open5gs +sed -i 's|NSSF_IP|'$NSSF_IP'|g' install/etc/open5gs/nssf.yaml +sed -i 's|NRF_IP|'$NRF_IP'|g' install/etc/open5gs/nssf.yaml +sed -i 's|SCP_IP|'$SCP_IP'|g' install/etc/open5gs/nssf.yaml +sed -i 's|NRF_IP|'$NRF_IP'|g' install/etc/open5gs/nssf.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/nssf.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/slicing/sa-deploy.yaml b/custom_deployments/slicing/sa-deploy.yaml new file mode 100644 index 0000000..a4e6955 --- /dev/null +++ b/custom_deployments/slicing/sa-deploy.yaml @@ -0,0 +1,401 @@ +services: + mongo: + image: mongo:6.0 + container_name: mongo + command: --bind_ip 0.0.0.0 + env_file: + - .custom_env + volumes: + - mongodbdata:/data/db + - mongodbdata:/data/configdb + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "27017/udp" + - "27017/tcp" + networks: + default: + ipv4_address: ${MONGO_IP} + webui: + image: docker_open5gs + container_name: webui + depends_on: + - mongo + env_file: + - .custom_env + environment: + - COMPONENT_NAME=webui + volumes: + - ../../webui:/mnt/webui + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9999/tcp" + ports: + - "9999:9999/tcp" + networks: + default: + ipv4_address: ${WEBUI_IP} + nrf: + image: docker_open5gs + container_name: nrf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=nrf + volumes: + - ../../nrf:/mnt/nrf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${NRF_IP} + scp: + image: docker_open5gs + depends_on: + - nrf + container_name: scp + env_file: + - .custom_env + environment: + - COMPONENT_NAME=scp + volumes: + - ../../scp:/mnt/scp + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${SCP_IP} + ausf: + image: docker_open5gs + depends_on: + - nrf + - scp + container_name: ausf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=ausf + volumes: + - ../../ausf:/mnt/ausf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${AUSF_IP} + udr: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: udr + env_file: + - .custom_env + environment: + - COMPONENT_NAME=udr + volumes: + - ../../udr:/mnt/udr + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${UDR_IP} + udm: + image: docker_open5gs + depends_on: + - nrf + - scp + container_name: udm + env_file: + - .custom_env + environment: + - COMPONENT_NAME=udm + volumes: + - ../../udm:/mnt/udm + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${UDM_IP} + smf: + image: docker_open5gs + depends_on: + - nrf + - scp + - amf + container_name: smf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=smf + - DEPLOY_MODE=5G + volumes: + - ./smf:/mnt/smf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "8805/udp" + - "2123/udp" + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${SMF_IP} + smf2: + image: docker_open5gs + depends_on: + - nrf + - scp + - amf + container_name: smf2 + env_file: + - .custom_env + environment: + - COMPONENT_NAME=smf2 + - DEPLOY_MODE=5G + volumes: + - ./smf:/mnt/smf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "8805/udp" + - "2123/udp" + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${SMF2_IP} + upf: + image: docker_open5gs + depends_on: + - nrf + - scp + - smf + container_name: upf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=upf + volumes: + - ./upf:/mnt/upf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2152/udp" + - "8805/udp" + - "9091/tcp" + # ports: + # - "2152:2152/udp" + cap_add: + - NET_ADMIN + privileged: true + sysctls: + - net.ipv4.ip_forward=1 + #- net.ipv6.conf.all.disable_ipv6=0 + networks: + default: + ipv4_address: ${UPF_IP} + upf2: + image: docker_open5gs + depends_on: + - nrf + - scp + - smf2 + container_name: upf2 + env_file: + - .custom_env + environment: + - COMPONENT_NAME=upf2 + volumes: + - ./upf:/mnt/upf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2152/udp" + - "8805/udp" + - "9091/tcp" + # ports: + # - "2152:2152/udp" + cap_add: + - NET_ADMIN + privileged: true + sysctls: + - net.ipv4.ip_forward=1 + #- net.ipv6.conf.all.disable_ipv6=0 + networks: + default: + ipv4_address: ${UPF2_IP} + amf: + image: docker_open5gs + depends_on: + - nrf + - scp + - ausf + - udm + - udr + - pcf + - bsf + container_name: amf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=amf + volumes: + - ./amf:/mnt/amf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "38412/sctp" + - "7777/tcp" + - "9091/tcp" + # ports: + # - "38412:38412/sctp" + networks: + default: + ipv4_address: ${AMF_IP} + pcf: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: pcf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=pcf + volumes: + - ../../pcf:/mnt/pcf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${PCF_IP} + bsf: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: bsf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=bsf + volumes: + - ../../bsf:/mnt/bsf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${BSF_IP} + nssf: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: nssf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=nssf + volumes: + - ./nssf:/mnt/nssf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${NSSF_IP} + metrics: + build: ../../metrics + image: docker_metrics + container_name: metrics + env_file: + - .custom_env + volumes: + - ../../metrics:/mnt/metrics + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9090/tcp" + ports: + - "9090:9090/tcp" + networks: + default: + ipv4_address: ${METRICS_IP} + grafana: + image: grafana/grafana:11.3.0 + container_name: grafana + env_file: + - .custom_env + volumes: + - grafana_data:/var/lib/grafana + - ../../grafana/:/etc/grafana/provisioning/ + - ../../grafana:/mnt/grafana + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} + #- GF_INSTALL_PLUGINS=${GRAFANA_INSTALL_PLUGINS} + - GF_PATHS_PROVISIONING=/etc/grafana/provisioning + - GF_PATHS_DATA=/var/lib/grafana + - METRICS_IP=${METRICS_IP} + expose: + - "3000/tcp" + ports: + - "3000:3000/tcp" + networks: + default: + ipv4_address: ${GRAFANA_IP} +networks: + default: + name: docker_open5gs_default + ipam: + config: + - subnet: ${TEST_NETWORK} +volumes: + grafana_data: + name: grafana_data + mongodbdata: + name: docker_open5gs_mongodbdata diff --git a/custom_deployments/slicing/smf/ip_utils.py b/custom_deployments/slicing/smf/ip_utils.py new file mode 100755 index 0000000..576535d --- /dev/null +++ b/custom_deployments/slicing/smf/ip_utils.py @@ -0,0 +1,70 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import click +import sys +import ipaddress + +""" +Script used to fetch first IP address in a given IP range. i.e. the calling bash script reads the std output + +Usage in command line: +e.g: +$ python3 ip_utils.py --ip_range 192.168.100.0/24 +$ python3 ip_utils.py --ip_range 2001:230:cafe::/48 +""" + + +def validate_ip_net(ctx, param, value): + try: + ip_net = ipaddress.ip_network(value) + return ip_net + except ValueError: + raise click.BadParameter( + 'Value does not represent a valid IPv4/IPv6 range') + + +@click.command() +@click.option('--ip_range', + required=True, + callback=validate_ip_net, + help='UE IPv4/IPv6 Address range in CIDR format e.g. 192.168.100.0/24 or 2001:230:cafe::/48') +def start(ip_range): + + # Get the first IP address in the IP range and netmask prefix length + first_ip_addr = next(ip_range.hosts(), None) + if not first_ip_addr: + raise ValueError('Invalid UE IPv4 range. Only one IP given') + else: + first_ip_addr = first_ip_addr.exploded + print(str(first_ip_addr)) + +if __name__ == '__main__': + try: + start() + sys.exit(0) + except ValueError: + sys.exit(1) diff --git a/custom_deployments/slicing/smf/smf.yaml b/custom_deployments/slicing/smf/smf.yaml new file mode 100644 index 0000000..461aee9 --- /dev/null +++ b/custom_deployments/slicing/smf/smf.yaml @@ -0,0 +1,64 @@ +logger: + file: + path: /open5gs/install/var/log/open5gs/smf.log + +sbi: + server: + no_tls: true + client: + no_tls: true + +global: + max: + ue: MAX_NUM_UE + parameter: + no_ipv4v6_local_addr_in_packet_filter: true + +smf: + info: + - s_nssai: + - sst: 1 + sd: 000001 + dnn: + - internet + sbi: + server: + - address: SMF_IP + port: 7777 + client: + nrf: + - uri: http://NRF_IP:7777 + scp: + - uri: http://SCP_IP:7777 + gtpc: + server: + - address: SMF_IP + gtpu: + server: + - address: SMF_IP + pfcp: + server: + - address: SMF_IP + client: + upf: + - address: UPF_IP + dnn: internet + session: + - subnet: UE_IPV4_INTERNET_APN_SUBNET + gateway: UE_IPV4_INTERNET_APN_GATEWAY_IP + dnn: internet + - subnet: 2001:230:cafe::/48 + gateway: 2001:230:cafe::1 + dnn: internet + dns: + - SMF_DNS1 + - SMF_DNS2 + - 2001:4860:4860::8888 + - 2001:4860:4860::8844 + p-cscf: + - PCSCF_IP + mtu: 1450 + metrics: + server: + - address: SMF_IP + port: 9091 diff --git a/custom_deployments/slicing/smf/smf2.yaml b/custom_deployments/slicing/smf/smf2.yaml new file mode 100644 index 0000000..b11877d --- /dev/null +++ b/custom_deployments/slicing/smf/smf2.yaml @@ -0,0 +1,64 @@ +logger: + file: + path: /open5gs/install/var/log/open5gs/smf2.log + +sbi: + server: + no_tls: true + client: + no_tls: true + +global: + max: + ue: MAX_NUM_UE + parameter: + no_ipv4v6_local_addr_in_packet_filter: true + +smf: + info: + - s_nssai: + - sst: 1 + sd: 000002 + dnn: + - private + sbi: + server: + - address: SMF2_IP + port: 7777 + client: + nrf: + - uri: http://NRF_IP:7777 + scp: + - uri: http://SCP_IP:7777 + gtpc: + server: + - address: SMF2_IP + gtpu: + server: + - address: SMF2_IP + pfcp: + server: + - address: SMF2_IP + client: + upf: + - address: UPF2_IP + dnn: private + session: + - subnet: UE_IPV4_PRIVATE_APN_SUBNET + gateway: UE_IPV4_PRIVATE_APN_GATEWAY_IP + dnn: private + - subnet: 2001:230:fafe::/48 + gateway: 2001:230:fafe::1 + dnn: private + dns: + - SMF_DNS1 + - SMF_DNS2 + - 2001:4860:4860::8888 + - 2001:4860:4860::8844 + p-cscf: + - PCSCF_IP + mtu: 1450 + metrics: + server: + - address: SMF2_IP + port: 9091 diff --git a/custom_deployments/slicing/smf/smf2_init.sh b/custom_deployments/slicing/smf/smf2_init.sh new file mode 100755 index 0000000..28bde72 --- /dev/null +++ b/custom_deployments/slicing/smf/smf2_init.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export LC_ALL=C.UTF-8 +export LANG=C.UTF-8 +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) +export IF_NAME=$(ip r | awk '/default/ { print $5 }') + +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +UE_IPV4_PRIVATE_APN_GATEWAY_IP=$(python3 /mnt/smf/ip_utils.py --ip_range $UE_IPV4_PRIVATE) + +cp /mnt/smf/smf2.yaml install/etc/open5gs/smf.yaml +if [[ ${DEPLOY_MODE} == 4G ]]; +then + echo "Error: Invalid deployment mode for SMF: '$DEPLOY_MODE'" + exit 1 +fi + +sed -i 's|SMF2_IP|'$SMF2_IP'|g' install/etc/open5gs/smf.yaml +sed -i 's|SCP_IP|'$SCP_IP'|g' install/etc/open5gs/smf.yaml +sed -i 's|NRF_IP|'$NRF_IP'|g' install/etc/open5gs/smf.yaml +sed -i 's|UPF2_IP|'$UPF2_IP'|g' install/etc/open5gs/smf.yaml +sed -i 's|SMF_DNS1|'$SMF_DNS1'|g' install/etc/open5gs/smf.yaml +sed -i 's|SMF_DNS2|'$SMF_DNS2'|g' install/etc/open5gs/smf.yaml +sed -i 's|UE_IPV4_PRIVATE_APN_GATEWAY_IP|'$UE_IPV4_PRIVATE_APN_GATEWAY_IP'|g' install/etc/open5gs/smf.yaml +sed -i 's|UE_IPV4_PRIVATE_APN_SUBNET|'$UE_IPV4_PRIVATE'|g' install/etc/open5gs/smf.yaml +sed -i 's|PCSCF_IP|'$PCSCF_IP'|g' install/etc/open5gs/smf.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/smf.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/slicing/smf/smf_init.sh b/custom_deployments/slicing/smf/smf_init.sh new file mode 100755 index 0000000..3b6803f --- /dev/null +++ b/custom_deployments/slicing/smf/smf_init.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export LC_ALL=C.UTF-8 +export LANG=C.UTF-8 +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) +export IF_NAME=$(ip r | awk '/default/ { print $5 }') + +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +UE_IPV4_INTERNET_APN_GATEWAY_IP=$(python3 /mnt/smf/ip_utils.py --ip_range $UE_IPV4_INTERNET) +UE_IPV4_IMS_TUN_IP=$(python3 /mnt/smf/ip_utils.py --ip_range $UE_IPV4_IMS) + +cp /mnt/smf/smf.yaml install/etc/open5gs +if [[ ${DEPLOY_MODE} == 4G ]]; +then + echo "Error: Invalid deployment mode for SMF: '$DEPLOY_MODE'" + exit 1 +fi + +sed -i 's|SMF_IP|'$SMF_IP'|g' install/etc/open5gs/smf.yaml +sed -i 's|SCP_IP|'$SCP_IP'|g' install/etc/open5gs/smf.yaml +sed -i 's|NRF_IP|'$NRF_IP'|g' install/etc/open5gs/smf.yaml +sed -i 's|UPF_IP|'$UPF_IP'|g' install/etc/open5gs/smf.yaml +sed -i 's|SMF_DNS1|'$SMF_DNS1'|g' install/etc/open5gs/smf.yaml +sed -i 's|SMF_DNS2|'$SMF_DNS2'|g' install/etc/open5gs/smf.yaml +sed -i 's|UE_IPV4_INTERNET_APN_GATEWAY_IP|'$UE_IPV4_INTERNET_APN_GATEWAY_IP'|g' install/etc/open5gs/smf.yaml +sed -i 's|UE_IPV4_INTERNET_APN_SUBNET|'$UE_IPV4_INTERNET'|g' install/etc/open5gs/smf.yaml +sed -i 's|UE_IPV4_IMS_TUN_IP|'$UE_IPV4_IMS_TUN_IP'|g' install/etc/open5gs/smf.yaml +sed -i 's|UE_IPV4_IMS_SUBNET|'$UE_IPV4_IMS'|g' install/etc/open5gs/smf.yaml +sed -i 's|PCSCF_IP|'$PCSCF_IP'|g' install/etc/open5gs/smf.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/smf.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/slicing/ueransim/ueransim-gnb.yaml b/custom_deployments/slicing/ueransim/ueransim-gnb.yaml new file mode 100644 index 0000000..d2ff9c6 --- /dev/null +++ b/custom_deployments/slicing/ueransim/ueransim-gnb.yaml @@ -0,0 +1,25 @@ +mcc: 'MCC' # Mobile Country Code value +mnc: 'MNC' # Mobile Network Code value (2 or 3 digits) + +nci: '0x000000010' # NR Cell Identity (36-bit) +idLength: 32 # NR gNB ID length in bits [22...32] +tac: TAC # Tracking Area Code + +linkIp: NR_GNB_IP # gNB's local IP address for Radio Link Simulation (Usually same with local IP) +ngapIp: NR_GNB_IP # gNB's local IP address for N2 Interface (Usually same with local IP) +gtpIp: NR_GNB_IP # gNB's local IP address for N3 Interface (Usually same with local IP) + +# List of AMF address information +amfConfigs: + - address: AMF_IP + port: 38412 + +# List of supported S-NSSAIs by this gNB +slices: + - sst: 1 + sd: 0x000001 + - sst: 1 + sd: 0x000002 + +# Indicates whether or not SCTP stream number errors should be ignored. +ignoreStreamIds: true diff --git a/custom_deployments/slicing/ueransim/ueransim-gnb_init.sh b/custom_deployments/slicing/ueransim/ueransim-gnb_init.sh new file mode 100755 index 0000000..51001b0 --- /dev/null +++ b/custom_deployments/slicing/ueransim/ueransim-gnb_init.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) + +cp /mnt/ueransim/${COMPONENT_NAME}.yaml /UERANSIM/config/${COMPONENT_NAME}.yaml + +sed -i 's|MNC|'$MNC'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|MCC|'$MCC'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|TAC|'$TAC'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|NR_GNB_IP|'$NR_GNB_IP'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|AMF_IP|'$AMF_IP'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/slicing/ueransim/ueransim-ue.yaml b/custom_deployments/slicing/ueransim/ueransim-ue.yaml new file mode 100644 index 0000000..dae3bea --- /dev/null +++ b/custom_deployments/slicing/ueransim/ueransim-ue.yaml @@ -0,0 +1,72 @@ +# IMSI number of the UE. IMSI = [MCC|MNC|MSISDN] (In total 15 or 16 digits) +supi: 'imsi-UE1_IMSI' +# Mobile Country Code value of HPLMN +mcc: 'MCC' +# Mobile Network Code value of HPLMN (2 or 3 digits) +mnc: 'MNC' + +# Permanent subscription key +key: 'UE1_KI' +# Operator code (OP or OPC) of the UE +op: 'UE1_OP' +# This value specifies the OP type and it can be either 'OP' or 'OPC' +opType: 'OP' +# Authentication Management Field (AMF) value +amf: 'UE1_AMF' +# IMEI number of the device. It is used if no SUPI is provided +imei: 'UE1_IMEI' +# IMEISV number of the device. It is used if no SUPI and IMEI is provided +imeiSv: 'UE1_IMEISV' + +# List of gNB IP addresses for Radio Link Simulation +gnbSearchList: + - NR_GNB_IP + +# UAC Access Identities Configuration +uacAic: + mps: false + mcs: false + +# UAC Access Control Class +uacAcc: + normalClass: 0 + class11: false + class12: false + class13: false + class14: false + class15: false + +# Initial PDU sessions to be established +sessions: + - type: 'IPv4' + apn: 'internet' + slice: + sst: 1 + sd: 0x000001 + +# Configured NSSAI for this UE by HPLMN +configured-nssai: + - sst: 1 + sd: 0x000001 + +# Default Configured NSSAI for this UE +default-nssai: + - sst: 1 + sd: 0x000001 + +# Supported encryption algorithms by this UE +integrity: + IA1: true + IA2: true + IA3: true + +# Supported integrity algorithms by this UE +ciphering: + EA1: true + EA2: true + EA3: true + +# Integrity protection maximum data rate for user plane +integrityMaxRate: + uplink: 'full' + downlink: 'full' diff --git a/custom_deployments/slicing/ueransim/ueransim-ue2.yaml b/custom_deployments/slicing/ueransim/ueransim-ue2.yaml new file mode 100644 index 0000000..f1e0a57 --- /dev/null +++ b/custom_deployments/slicing/ueransim/ueransim-ue2.yaml @@ -0,0 +1,72 @@ +# IMSI number of the UE. IMSI = [MCC|MNC|MSISDN] (In total 15 or 16 digits) +supi: 'imsi-UE2_IMSI' +# Mobile Country Code value of HPLMN +mcc: 'MCC' +# Mobile Network Code value of HPLMN (2 or 3 digits) +mnc: 'MNC' + +# Permanent subscription key +key: 'UE2_KI' +# Operator code (OP or OPC) of the UE +op: 'UE2_OP' +# This value specifies the OP type and it can be either 'OP' or 'OPC' +opType: 'OP' +# Authentication Management Field (AMF) value +amf: 'UE2_AMF' +# IMEI number of the device. It is used if no SUPI is provided +imei: 'UE2_IMEI' +# IMEISV number of the device. It is used if no SUPI and IMEI is provided +imeiSv: 'UE2_IMEISV' + +# List of gNB IP addresses for Radio Link Simulation +gnbSearchList: + - NR_GNB_IP + +# UAC Access Identities Configuration +uacAic: + mps: false + mcs: false + +# UAC Access Control Class +uacAcc: + normalClass: 0 + class11: false + class12: false + class13: false + class14: false + class15: false + +# Initial PDU sessions to be established +sessions: + - type: 'IPv4' + apn: 'private' + slice: + sst: 1 + sd: 0x000002 + +# Configured NSSAI for this UE by HPLMN +configured-nssai: + - sst: 1 + sd: 0x000002 + +# Default Configured NSSAI for this UE +default-nssai: + - sst: 1 + sd: 0x000002 + +# Supported encryption algorithms by this UE +integrity: + IA1: true + IA2: true + IA3: true + +# Supported integrity algorithms by this UE +ciphering: + EA1: true + EA2: true + EA3: true + +# Integrity protection maximum data rate for user plane +integrityMaxRate: + uplink: 'full' + downlink: 'full' diff --git a/custom_deployments/slicing/ueransim/ueransim-ue2_init.sh b/custom_deployments/slicing/ueransim/ueransim-ue2_init.sh new file mode 100755 index 0000000..9245043 --- /dev/null +++ b/custom_deployments/slicing/ueransim/ueransim-ue2_init.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) + +cp /mnt/ueransim/${COMPONENT_NAME}.yaml /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|MNC|'$MNC'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|MCC|'$MCC'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml + +sed -i 's|UE2_KI|'$UE2_KI'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|UE2_OP|'$UE2_OP'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|UE2_AMF|'$UE2_AMF'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|UE2_IMEISV|'$UE2_IMEISV'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|UE2_IMEI|'$UE2_IMEI'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|UE2_IMSI|'$UE2_IMSI'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|NR_GNB_IP|'$NR_GNB_IP'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/slicing/ueransim/ueransim-ue_init.sh b/custom_deployments/slicing/ueransim/ueransim-ue_init.sh new file mode 100755 index 0000000..a11ecca --- /dev/null +++ b/custom_deployments/slicing/ueransim/ueransim-ue_init.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) + +cp /mnt/ueransim/${COMPONENT_NAME}.yaml /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|MNC|'$MNC'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|MCC|'$MCC'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml + +sed -i 's|UE1_KI|'$UE1_KI'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|UE1_OP|'$UE1_OP'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|UE1_AMF|'$UE1_AMF'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|UE1_IMEISV|'$UE1_IMEISV'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|UE1_IMEI|'$UE1_IMEI'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|UE1_IMSI|'$UE1_IMSI'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml +sed -i 's|NR_GNB_IP|'$NR_GNB_IP'|g' /UERANSIM/config/${COMPONENT_NAME}.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/slicing/upf/ip_utils.py b/custom_deployments/slicing/upf/ip_utils.py new file mode 100755 index 0000000..576535d --- /dev/null +++ b/custom_deployments/slicing/upf/ip_utils.py @@ -0,0 +1,70 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import click +import sys +import ipaddress + +""" +Script used to fetch first IP address in a given IP range. i.e. the calling bash script reads the std output + +Usage in command line: +e.g: +$ python3 ip_utils.py --ip_range 192.168.100.0/24 +$ python3 ip_utils.py --ip_range 2001:230:cafe::/48 +""" + + +def validate_ip_net(ctx, param, value): + try: + ip_net = ipaddress.ip_network(value) + return ip_net + except ValueError: + raise click.BadParameter( + 'Value does not represent a valid IPv4/IPv6 range') + + +@click.command() +@click.option('--ip_range', + required=True, + callback=validate_ip_net, + help='UE IPv4/IPv6 Address range in CIDR format e.g. 192.168.100.0/24 or 2001:230:cafe::/48') +def start(ip_range): + + # Get the first IP address in the IP range and netmask prefix length + first_ip_addr = next(ip_range.hosts(), None) + if not first_ip_addr: + raise ValueError('Invalid UE IPv4 range. Only one IP given') + else: + first_ip_addr = first_ip_addr.exploded + print(str(first_ip_addr)) + +if __name__ == '__main__': + try: + start() + sys.exit(0) + except ValueError: + sys.exit(1) diff --git a/custom_deployments/slicing/upf/tun_if.py b/custom_deployments/slicing/upf/tun_if.py new file mode 100755 index 0000000..8edb1a9 --- /dev/null +++ b/custom_deployments/slicing/upf/tun_if.py @@ -0,0 +1,111 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import click +import subprocess +import ipaddress + +""" +Usage in command line: +e.g: +$ python3 tun_if.py --tun_ifname ogstun --tun_ifmode tun --ipv4_range 192.168.100.0/24 --ipv6_range 2001:230:cafe::/48 +""" + + +def validate_ip_net(ctx, param, value): + try: + ip_net = ipaddress.ip_network(value) + return ip_net + except ValueError: + raise click.BadParameter( + 'Value does not represent a valid IPv4/IPv6 range') + + +@click.command() +@click.option('--tun_ifname', + required=True, + help='TUN interface name e.g. ogstun') +@click.option('--tun_ifmode', + required=True, + type=click.Choice(['tun', 'tap']), + help='TUN interface mode e.g. tun or tap') +@click.option('--ipv4_range', + required=True, + callback=validate_ip_net, + help='UE IPv4 Address range in CIDR format e.g. 192.168.100.0/24') +@click.option('--ipv6_range', + required=True, + callback=validate_ip_net, + help='UE IPv6 Address range in CIDR format e.g. 2001:230:cafe::/48') +@click.option('--nat_rule', + default='yes', + help='Option specifying whether to add NATing iptables rule or not') +def start(tun_ifname, + tun_ifmode, + ipv4_range, + ipv6_range, + nat_rule): + + # Get the first IP address in the IP range and netmask prefix length + first_ipv4_addr = next(ipv4_range.hosts(), None) + if not first_ipv4_addr: + raise ValueError('Invalid UE IPv4 range. Only one IP given') + else: + first_ipv4_addr = first_ipv4_addr.exploded + first_ipv6_addr = next(ipv6_range.hosts(), None) + if not first_ipv6_addr: + raise ValueError('Invalid UE IPv6 range. Only one IP given') + else: + first_ipv6_addr = first_ipv6_addr.exploded + + ipv4_netmask_prefix = ipv4_range.prefixlen + ipv6_netmask_prefix = ipv6_range.prefixlen + + # Setup the TUN/TAP interface, set IP address and setup IPtables + execute_bash_cmd('ip tuntap add name ' + tun_ifname + ' mode ' + tun_ifmode) + execute_bash_cmd('ip addr add ' + first_ipv4_addr + '/' + + str(ipv4_netmask_prefix) + ' dev ' + tun_ifname) + execute_bash_cmd('ip addr add ' + first_ipv6_addr + '/' + + str(ipv6_netmask_prefix) + ' dev ' + tun_ifname) + execute_bash_cmd('ip link set ' + tun_ifname + ' mtu 1450') + execute_bash_cmd('ip link set ' + tun_ifname + ' up') + if nat_rule == 'yes': + execute_bash_cmd('if ! iptables-save | grep -- \"-A POSTROUTING -s ' + ipv4_range.with_prefixlen + ' ! -o ' + tun_ifname + ' -j MASQUERADE\" ; then ' + + 'iptables -t nat -A POSTROUTING -s ' + ipv4_range.with_prefixlen + ' ! -o ' + tun_ifname + ' -j MASQUERADE; fi') + execute_bash_cmd('if ! ip6tables-save | grep -- \"-A POSTROUTING -s ' + ipv6_range.with_prefixlen + ' ! -o ' + tun_ifname + ' -j MASQUERADE\" ; then ' + + 'ip6tables -t nat -A POSTROUTING -s ' + ipv6_range.with_prefixlen + ' ! -o ' + tun_ifname + ' -j MASQUERADE; fi') + execute_bash_cmd('if ! iptables-save | grep -- \"-A INPUT -i ' + tun_ifname + ' -j ACCEPT\" ; then ' + + 'iptables -A INPUT -i ' + tun_ifname + ' -j ACCEPT; fi') + execute_bash_cmd('if ! ip6tables-save | grep -- \"-A INPUT -i ' + tun_ifname + ' -j ACCEPT\" ; then ' + + 'ip6tables -A INPUT -i ' + tun_ifname + ' -j ACCEPT; fi') + + +def execute_bash_cmd(bash_cmd): + return subprocess.run(bash_cmd, stdout=subprocess.PIPE, shell=True) + + +if __name__ == '__main__': + start() diff --git a/custom_deployments/slicing/upf/upf.yaml b/custom_deployments/slicing/upf/upf.yaml new file mode 100644 index 0000000..5c9e3cc --- /dev/null +++ b/custom_deployments/slicing/upf/upf.yaml @@ -0,0 +1,33 @@ +logger: + file: + path: /open5gs/install/var/log/open5gs/upf.log + +global: + max: + ue: MAX_NUM_UE + +upf: + pfcp: + server: + - address: UPF_IP + client: + smf: + - address: SMF_IP + dnn: internet + gtpu: + server: + - address: UPF_IP + advertise: UPF_ADVERTISE_IP + session: + - subnet: UE_IPV4_INTERNET_APN_SUBNET + gateway: UE_IPV4_INTERNET_APN_GATEWAY_IP + dnn: internet + dev: UPF_INTERNET_APN_IF_NAME + - subnet: 2001:230:cafe::/48 + gateway: 2001:230:cafe::1 + dnn: internet + dev: UPF_INTERNET_APN_IF_NAME + metrics: + server: + - address: UPF_IP + port: 9091 diff --git a/custom_deployments/slicing/upf/upf2.yaml b/custom_deployments/slicing/upf/upf2.yaml new file mode 100644 index 0000000..c0d1dd2 --- /dev/null +++ b/custom_deployments/slicing/upf/upf2.yaml @@ -0,0 +1,33 @@ +logger: + file: + path: /open5gs/install/var/log/open5gs/upf2.log + +global: + max: + ue: MAX_NUM_UE + +upf: + pfcp: + server: + - address: UPF2_IP + client: + smf: + - address: SMF2_IP + dnn: private + gtpu: + server: + - address: UPF2_IP + advertise: UPF2_ADVERTISE_IP + session: + - subnet: UE_IPV4_PRIVATE_APN_SUBNET + gateway: UE_IPV4_PRIVATE_APN_GATEWAY_IP + dnn: private + dev: UPF2_PRIVATE_APN_IF_NAME + - subnet: 2001:230:fafe::/48 + gateway: 2001:230:fafe::1 + dnn: private + dev: UPF2_PRIVATE_APN_IF_NAME + metrics: + server: + - address: UPF2_IP + port: 9091 diff --git a/custom_deployments/slicing/upf/upf2_init.sh b/custom_deployments/slicing/upf/upf2_init.sh new file mode 100755 index 0000000..cfd0327 --- /dev/null +++ b/custom_deployments/slicing/upf/upf2_init.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export LC_ALL=C.UTF-8 +export LANG=C.UTF-8 +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) +export IF_NAME=$(ip r | awk '/default/ { print $5 }') + +# use nftables instead of iptables +update-alternatives --set iptables `which iptables-nft` +update-alternatives --set ip6tables `which ip6tables-nft` + +# Remove UPF Interfaces if they exist +ip link delete $UPF2_PRIVATE_APN_IF_NAME 2>/dev/null + +# Validate interface names based on UPF2_TUNTAP_MODE +if [ "$UPF2_TUNTAP_MODE" = "tap" ]; then + if [[ "$UPF2_PRIVATE_APN_IF_NAME" != *"tap"* ]] || [[ "$UPF_IMS_APN_IF_NAME" != *"tap"* ]]; then + echo "Error: When UPF2_TUNTAP_MODE is 'tap', both UPF2_PRIVATE_APN_IF_NAME and UPF_IMS_APN_IF_NAME must contain 'tap'" + exit 1 + fi +elif [ "$UPF2_TUNTAP_MODE" = "tun" ]; then + if [[ "$UPF2_PRIVATE_APN_IF_NAME" == *"tap"* ]] || [[ "$UPF_IMS_APN_IF_NAME" == *"tap"* ]]; then + echo "Error: When UPF2_TUNTAP_MODE is 'tun', UPF2_PRIVATE_APN_IF_NAME and UPF_IMS_APN_IF_NAME must not contain 'tap'" + exit 1 + fi +else + echo "Error: UPF2_TUNTAP_MODE must be either 'tap' or 'tun'" + exit 1 +fi + +python3 /mnt/upf/tun_if.py --tun_ifname $UPF2_PRIVATE_APN_IF_NAME --tun_ifmode $UPF2_TUNTAP_MODE --ipv4_range $UE_IPV4_PRIVATE --ipv6_range 2001:230:fafe::/48 + +UE_IPV4_PRIVATE_APN_GATEWAY_IP=$(python3 /mnt/upf/ip_utils.py --ip_range $UE_IPV4_PRIVATE) + +cp /mnt/upf/upf2.yaml install/etc/open5gs/upf.yaml + +sed -i 's|UPF2_IP|'$UPF2_IP'|g' install/etc/open5gs/upf.yaml +sed -i 's|SMF2_IP|'$SMF2_IP'|g' install/etc/open5gs/upf.yaml +sed -i 's|UE_IPV4_PRIVATE_APN_GATEWAY_IP|'$UE_IPV4_PRIVATE_APN_GATEWAY_IP'|g' install/etc/open5gs/upf.yaml +sed -i 's|UE_IPV4_PRIVATE_APN_SUBNET|'$UE_IPV4_PRIVATE'|g' install/etc/open5gs/upf.yaml +sed -i 's|UPF2_ADVERTISE_IP|'$UPF2_ADVERTISE_IP'|g' install/etc/open5gs/upf.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/upf.yaml +sed -i 's|UPF2_PRIVATE_APN_IF_NAME|'$UPF2_PRIVATE_APN_IF_NAME'|g' install/etc/open5gs/upf.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/slicing/upf/upf_init.sh b/custom_deployments/slicing/upf/upf_init.sh new file mode 100755 index 0000000..9717a29 --- /dev/null +++ b/custom_deployments/slicing/upf/upf_init.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export LC_ALL=C.UTF-8 +export LANG=C.UTF-8 +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) +export IF_NAME=$(ip r | awk '/default/ { print $5 }') + +# use nftables instead of iptables +update-alternatives --set iptables `which iptables-nft` +update-alternatives --set ip6tables `which ip6tables-nft` + +# Remove UPF Interfaces if they exist +ip link delete $UPF_INTERNET_APN_IF_NAME 2>/dev/null + +# Validate interface names based on UPF_TUNTAP_MODE +if [ "$UPF_TUNTAP_MODE" = "tap" ]; then + if [[ "$UPF_INTERNET_APN_IF_NAME" != *"tap"* ]] || [[ "$UPF_IMS_APN_IF_NAME" != *"tap"* ]]; then + echo "Error: When UPF_TUNTAP_MODE is 'tap', both UPF_INTERNET_APN_IF_NAME and UPF_IMS_APN_IF_NAME must contain 'tap'" + exit 1 + fi +elif [ "$UPF_TUNTAP_MODE" = "tun" ]; then + if [[ "$UPF_INTERNET_APN_IF_NAME" == *"tap"* ]] || [[ "$UPF_IMS_APN_IF_NAME" == *"tap"* ]]; then + echo "Error: When UPF_TUNTAP_MODE is 'tun', UPF_INTERNET_APN_IF_NAME and UPF_IMS_APN_IF_NAME must not contain 'tap'" + exit 1 + fi +else + echo "Error: UPF_TUNTAP_MODE must be either 'tap' or 'tun'" + exit 1 +fi + +python3 /mnt/upf/tun_if.py --tun_ifname $UPF_INTERNET_APN_IF_NAME --tun_ifmode $UPF_TUNTAP_MODE --ipv4_range $UE_IPV4_INTERNET --ipv6_range 2001:230:cafe::/48 + +UE_IPV4_INTERNET_APN_GATEWAY_IP=$(python3 /mnt/upf/ip_utils.py --ip_range $UE_IPV4_INTERNET) + +cp /mnt/upf/upf.yaml install/etc/open5gs +sed -i 's|UPF_IP|'$UPF_IP'|g' install/etc/open5gs/upf.yaml +sed -i 's|SMF_IP|'$SMF_IP'|g' install/etc/open5gs/upf.yaml +sed -i 's|UE_IPV4_INTERNET_APN_GATEWAY_IP|'$UE_IPV4_INTERNET_APN_GATEWAY_IP'|g' install/etc/open5gs/upf.yaml +sed -i 's|UE_IPV4_INTERNET_APN_SUBNET|'$UE_IPV4_INTERNET'|g' install/etc/open5gs/upf.yaml +sed -i 's|UE_IPV4_IMS_TUN_IP|'$UE_IPV4_IMS_TUN_IP'|g' install/etc/open5gs/upf.yaml +sed -i 's|UE_IPV4_IMS_SUBNET|'$UE_IPV4_IMS'|g' install/etc/open5gs/upf.yaml +sed -i 's|UPF_ADVERTISE_IP|'$UPF_ADVERTISE_IP'|g' install/etc/open5gs/upf.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/upf.yaml +sed -i 's|UPF_INTERNET_APN_IF_NAME|'$UPF_INTERNET_APN_IF_NAME'|g' install/etc/open5gs/upf.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/custom_deployments/with_eupf/.custom_env b/custom_deployments/with_eupf/.custom_env new file mode 100644 index 0000000..f440507 --- /dev/null +++ b/custom_deployments/with_eupf/.custom_env @@ -0,0 +1,152 @@ +# Set proper timezone to sync times between docker host and containers +#TZ=Europe/Berlin + +MCC=001 +MNC=01 +TAC=1 + +TEST_NETWORK=172.22.0.0/24 +DOCKER_HOST_IP=192.168.1.223 + +# MONGODB +MONGO_IP=172.22.0.2 + +# HSS - open5gs +HSS_IP=172.22.0.3 + +# PCRF +PCRF_IP=172.22.0.4 +PCRF_BIND_PORT=3873 + +# SGW +SGWC_IP=172.22.0.5 +SGWU_IP=172.22.0.6 +SGWU_ADVERTISE_IP=172.22.0.6 + +# SMF +SMF_IP=172.22.0.7 +SMF_DNS1=8.8.8.8 +SMF_DNS2=8.8.4.4 + +# UPF +UPF_IP=172.22.0.8 +UPF_ADVERTISE_IP=172.22.0.8 +# Allowed values for UPF_TUNTAP_MODE are 'tun' or 'tap' +# If 'tap' is used as IF mode, then UPF_INTERNET_APN_IF_NAME and UPF_IMS_APN_IF_NAME must contain string 'tap' +UPF_TUNTAP_MODE=tun +UPF_INTERNET_APN_IF_NAME=ogstun +UPF_IMS_APN_IF_NAME=ogstun2 + +# MME +MME_IP=172.22.0.9 + +# AMF +AMF_IP=172.22.0.10 + +# AUSF +AUSF_IP=172.22.0.11 + +# NRF +NRF_IP=172.22.0.12 + +# UDM +UDM_IP=172.22.0.13 + +# UDR +UDR_IP=172.22.0.14 + +# IMS DNS +DNS_IP=172.22.0.15 + +# RTPENGINE +RTPENGINE_IP=172.22.0.16 + +# MYSQL +MYSQL_IP=172.22.0.17 + +# PYHSS +PYHSS_IP=172.22.0.18 +PYHSS_BIND_PORT=3875 + +# ICSCF +ICSCF_IP=172.22.0.19 +ICSCF_BIND_PORT=3869 + +# SCSCF +SCSCF_IP=172.22.0.20 +SCSCF_BIND_PORT=3870 + +# PCSCF +PCSCF_IP=172.22.0.21 +PCSCF_BIND_PORT=3871 + +# SRSLTE ENB +SRS_ENB_IP=172.22.0.22 + +# UERANSIM +NR_GNB_IP=172.22.0.23 +NR_UE_IP=172.22.0.24 + +UE1_IMEI=356938035643803 +UE1_IMEISV=4370816125816151 +UE1_IMSI=001011234567895 +UE1_KI=8baf473f2f8fd09487cccbd7097c6862 +UE1_OP=11111111111111111111111111111111 +UE1_AMF=8000 + +# OAI ENB +OAI_ENB_IP=172.22.0.25 + +# OPEN5GS WEBUI +WEBUI_IP=172.22.0.26 + +# PCF +PCF_IP=172.22.0.27 + +# NSSF +NSSF_IP=172.22.0.28 + +# BSF +BSF_IP=172.22.0.29 + +# ENTITLEMENT SERVER +ENTITLEMENT_SERVER_IP=172.22.0.30 + +# OSMOMSC +OSMOMSC_IP=172.22.0.31 + +# OSMOHLR +OSMOHLR_IP=172.22.0.32 + +# SMSC +SMSC_IP=172.22.0.33 + +# SRSLTE UE +SRS_UE_IP=172.22.0.34 + +# SCP +SCP_IP=172.22.0.35 + +# METRICS +METRICS_IP=172.22.0.36 + +# SRSRAN GNB +SRS_GNB_IP=172.22.0.37 + +# GRAFANA +GRAFANA_IP=172.22.0.39 +GRAFANA_USERNAME=open5gs +GRAFANA_PASSWORD=open5gs + +# OCS +OCS_IP=172.22.0.40 +OCS_BIND_PORT=3872 + +# UE IPv4 Subnet Range for APN=internet +UE_IPV4_INTERNET=192.168.100.0/24 + +# UE IPv4 Subnet Range for APN=ims +UE_IPV4_IMS=192.168.101.0/24 + +# Maximum Number of UEs +MAX_NUM_UE=1024 diff --git a/custom_deployments/with_eupf/README.md b/custom_deployments/with_eupf/README.md new file mode 100644 index 0000000..b21886b --- /dev/null +++ b/custom_deployments/with_eupf/README.md @@ -0,0 +1,27 @@ +## Deployment description + +This custom deployment uses eUPF (https://github.com/edgecomllc/eupf) rather than open5gs UPF for 5G SA network deployment + +## Additional steps + +Most of the steps to be followed are similar to the steps mentioned in the [README in the root folder](../../README.md). However, additional steps mentioned below must be taken into account while deploying this custom deployment scenario. + +### Build docker images for eUPF + +eUPF docker image needs to be built before deploying + +``` +cd ../../eupf +docker build --no-cache --force-rm -t docker_eupf . +``` + +### Loading environmental variables for custom deployment + +**Warning** +For custom deployments, you must modify/use only the [**.custom_env**](.custom_env) file rather than the [**.env** in the root folder](../../.env). + +``` +set -a +source .custom_env +set +a +``` diff --git a/custom_deployments/with_eupf/nr-gnb.yaml b/custom_deployments/with_eupf/nr-gnb.yaml new file mode 100644 index 0000000..c37d54e --- /dev/null +++ b/custom_deployments/with_eupf/nr-gnb.yaml @@ -0,0 +1,29 @@ +version: '3' +services: + nr_gnb: + image: docker_ueransim + container_name: nr_gnb + stdin_open: true + tty: true + volumes: + - ../../ueransim:/mnt/ueransim + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=ueransim-gnb + expose: + - "38412/sctp" + - "2152/udp" + - "4997/udp" + cap_add: + - NET_ADMIN + privileged: true + networks: + default: + ipv4_address: ${NR_GNB_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/custom_deployments/with_eupf/nr-ue.yaml b/custom_deployments/with_eupf/nr-ue.yaml new file mode 100644 index 0000000..b2d47ee --- /dev/null +++ b/custom_deployments/with_eupf/nr-ue.yaml @@ -0,0 +1,27 @@ +version: '3' +services: + nr_ue: + image: docker_ueransim + container_name: nr_ue + stdin_open: true + tty: true + volumes: + - ../../ueransim:/mnt/ueransim + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=ueransim-ue + expose: + - "4997/udp" + cap_add: + - NET_ADMIN + privileged: true + networks: + default: + ipv4_address: ${NR_UE_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/custom_deployments/with_eupf/oaignb.yaml b/custom_deployments/with_eupf/oaignb.yaml new file mode 100644 index 0000000..2af874e --- /dev/null +++ b/custom_deployments/with_eupf/oaignb.yaml @@ -0,0 +1,34 @@ +version: '3' +services: + oaignb: + build: + context: oai + dockerfile: gnb_dockerfile + image: docker_oai_gnb + container_name: oaignb + stdin_open: true + tty: true + privileged: true + sysctls: + - net.ipv4.ip_forward=1 + devices: + - "/dev/bus" + volumes: + - /dev/serial:/dev/serial:ro + - /dev/bus/usb:/dev/bus/usb:ro + - ../../oai:/mnt/oai + - ../../log:/openairinterface5g/cmake_targets/log/ + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + expose: + - "38412/sctp" + - "2152/udp" + networks: + default: + ipv4_address: ${OAI_ENB_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/custom_deployments/with_eupf/sa-deploy.yaml b/custom_deployments/with_eupf/sa-deploy.yaml new file mode 100644 index 0000000..91203a7 --- /dev/null +++ b/custom_deployments/with_eupf/sa-deploy.yaml @@ -0,0 +1,362 @@ +services: + mongo: + image: mongo:6.0 + container_name: mongo + command: --bind_ip 0.0.0.0 + env_file: + - .custom_env + volumes: + - mongodbdata:/data/db + - mongodbdata:/data/configdb + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "27017/udp" + - "27017/tcp" + networks: + default: + ipv4_address: ${MONGO_IP} + webui: + image: docker_open5gs + container_name: webui + depends_on: + - mongo + env_file: + - .custom_env + environment: + - COMPONENT_NAME=webui + volumes: + - ../../webui:/mnt/webui + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9999/tcp" + ports: + - "9999:9999/tcp" + networks: + default: + ipv4_address: ${WEBUI_IP} + nrf: + image: docker_open5gs + container_name: nrf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=nrf + volumes: + - ../../nrf:/mnt/nrf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${NRF_IP} + scp: + image: docker_open5gs + depends_on: + - nrf + container_name: scp + env_file: + - .custom_env + environment: + - COMPONENT_NAME=scp + volumes: + - ../../scp:/mnt/scp + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${SCP_IP} + ausf: + image: docker_open5gs + depends_on: + - nrf + - scp + container_name: ausf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=ausf + volumes: + - ../../ausf:/mnt/ausf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${AUSF_IP} + udr: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: udr + env_file: + - .custom_env + environment: + - COMPONENT_NAME=udr + volumes: + - ../../udr:/mnt/udr + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${UDR_IP} + udm: + image: docker_open5gs + depends_on: + - nrf + - scp + container_name: udm + env_file: + - .custom_env + environment: + - COMPONENT_NAME=udm + volumes: + - ../../udm:/mnt/udm + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${UDM_IP} + smf: + image: docker_open5gs + depends_on: + - nrf + - scp + - amf + container_name: smf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=smf + - DEPLOY_MODE=5G + volumes: + - ../../smf:/mnt/smf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "8805/udp" + - "2123/udp" + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${SMF_IP} + eupf: + image: docker_eupf + depends_on: + - nrf + - scp + - smf + container_name: eupf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=eupf + volumes: + - ../../eupf:/mnt/eupf + - /sys/fs/bpf:/sys/fs/bpf + - /sys/kernel/debug:/sys/kernel/debug:ro + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2152/udp" + - "8805/udp" + - "9091/tcp" + - "8181/tcp" + # ports: + # - "2152:2152/udp" + ulimits: + memlock: -1 + cap_add: + - NET_ADMIN + - SYS_ADMIN + privileged: true + sysctls: + - net.ipv4.conf.all.forwarding=1 + #- net.ipv6.conf.all.disable_ipv6=0 + networks: + default: + ipv4_address: ${UPF_IP} + eupf-routes: + image: nicolaka/netshoot + network_mode: host + privileged: true + container_name: eupf-routes + env_file: + - .custom_env + command: + - /bin/sh + - -c + - | + ip ro add ${UE_IPV4_INTERNET} via ${UPF_IP} && \ + iptables -t nat -A POSTROUTING -s ${UE_IPV4_INTERNET} -j MASQUERADE && \ + sysctl -w net.ipv4.conf.all.accept_local=1 + echo "done" + tail -f /dev/null + amf: + image: docker_open5gs + depends_on: + - nrf + - scp + - ausf + - udm + - udr + - pcf + - bsf + container_name: amf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=amf + volumes: + - ../../amf:/mnt/amf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "38412/sctp" + - "7777/tcp" + - "9091/tcp" + # ports: + # - "38412:38412/sctp" + networks: + default: + ipv4_address: ${AMF_IP} + pcf: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: pcf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=pcf + volumes: + - ../../pcf:/mnt/pcf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${PCF_IP} + bsf: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: bsf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=bsf + volumes: + - ../../bsf:/mnt/bsf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${BSF_IP} + nssf: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: nssf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=nssf + volumes: + - ../../nssf:/mnt/nssf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${NSSF_IP} + metrics: + build: ../../metrics + image: docker_metrics + container_name: metrics + env_file: + - .custom_env + volumes: + - ../../metrics:/mnt/metrics + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9090/tcp" + ports: + - "9090:9090/tcp" + networks: + default: + ipv4_address: ${METRICS_IP} + grafana: + image: grafana/grafana:11.3.0 + container_name: grafana + env_file: + - .custom_env + volumes: + - grafana_data:/var/lib/grafana + - ../../grafana/:/etc/grafana/provisioning/ + - ../../grafana:/mnt/grafana + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} + #- GF_INSTALL_PLUGINS=${GRAFANA_INSTALL_PLUGINS} + - GF_PATHS_PROVISIONING=/etc/grafana/provisioning + - GF_PATHS_DATA=/var/lib/grafana + - METRICS_IP=${METRICS_IP} + expose: + - "3000/tcp" + ports: + - "3000:3000/tcp" + networks: + default: + ipv4_address: ${GRAFANA_IP} +networks: + default: + name: docker_open5gs_default + ipam: + config: + - subnet: ${TEST_NETWORK} +volumes: + grafana_data: + name: grafana_data + mongodbdata: + name: docker_open5gs_mongodbdata diff --git a/custom_deployments/with_eupf/sa-vonr-deploy.yaml b/custom_deployments/with_eupf/sa-vonr-deploy.yaml new file mode 100644 index 0000000..bb3112b --- /dev/null +++ b/custom_deployments/with_eupf/sa-vonr-deploy.yaml @@ -0,0 +1,549 @@ +services: + mongo: + image: mongo:6.0 + container_name: mongo + command: --bind_ip 0.0.0.0 + env_file: + - .custom_env + volumes: + - mongodbdata:/data/db + - mongodbdata:/data/configdb + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "27017/udp" + - "27017/tcp" + networks: + default: + ipv4_address: ${MONGO_IP} + webui: + image: docker_open5gs + container_name: webui + depends_on: + - mongo + env_file: + - .custom_env + environment: + - COMPONENT_NAME=webui + volumes: + - ../../webui:/mnt/webui + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9999/tcp" + ports: + - "9999:9999/tcp" + networks: + default: + ipv4_address: ${WEBUI_IP} + nrf: + image: docker_open5gs + container_name: nrf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=nrf + volumes: + - ../../nrf:/mnt/nrf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${NRF_IP} + scp: + image: docker_open5gs + depends_on: + - nrf + container_name: scp + env_file: + - .custom_env + environment: + - COMPONENT_NAME=scp + volumes: + - ../../scp:/mnt/scp + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${SCP_IP} + ausf: + image: docker_open5gs + depends_on: + - nrf + - scp + container_name: ausf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=ausf + volumes: + - ../../ausf:/mnt/ausf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${AUSF_IP} + udr: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: udr + env_file: + - .custom_env + environment: + - COMPONENT_NAME=udr + volumes: + - ../../udr:/mnt/udr + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${UDR_IP} + udm: + image: docker_open5gs + depends_on: + - nrf + - scp + container_name: udm + env_file: + - .custom_env + environment: + - COMPONENT_NAME=udm + volumes: + - ../../udm:/mnt/udm + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${UDM_IP} + smf: + image: docker_open5gs + depends_on: + - nrf + - scp + - amf + container_name: smf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=smf + - DEPLOY_MODE=5G + volumes: + - ../../smf:/mnt/smf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "8805/udp" + - "2123/udp" + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${SMF_IP} + eupf: + image: docker_eupf + depends_on: + - nrf + - scp + - smf + container_name: eupf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=eupf + volumes: + - ../../eupf:/mnt/eupf + - /sys/fs/bpf:/sys/fs/bpf + - /sys/kernel/debug:/sys/kernel/debug:ro + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2152/udp" + - "8805/udp" + - "9091/tcp" + - "8181/tcp" + # ports: + # - "2152:2152/udp" + ulimits: + memlock: -1 + cap_add: + - NET_ADMIN + - SYS_ADMIN + privileged: true + sysctls: + - net.ipv4.conf.all.forwarding=1 + #- net.ipv6.conf.all.disable_ipv6=0 + networks: + default: + ipv4_address: ${UPF_IP} + eupf-routes: + image: nicolaka/netshoot + network_mode: host + privileged: true + container_name: eupf-routes + env_file: + - .custom_env + command: + - /bin/sh + - -c + - | + ip ro add ${UE_IPV4_INTERNET} via ${UPF_IP} && \ + iptables -t nat -A POSTROUTING -s ${UE_IPV4_INTERNET} -j MASQUERADE && \ + sysctl -w net.ipv4.conf.all.accept_local=1 + echo "done" + tail -f /dev/null + amf: + image: docker_open5gs + depends_on: + - nrf + - scp + - ausf + - udm + - udr + - pcf + - bsf + container_name: amf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=amf + volumes: + - ../../amf:/mnt/amf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "38412/sctp" + - "7777/tcp" + - "9091/tcp" + # ports: + # - "38412:38412/sctp" + networks: + default: + ipv4_address: ${AMF_IP} + pcf: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: pcf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=pcf + volumes: + - ../../pcf:/mnt/pcf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${PCF_IP} + bsf: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: bsf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=bsf + volumes: + - ../../bsf:/mnt/bsf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${BSF_IP} + nssf: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: nssf + env_file: + - .custom_env + environment: + - COMPONENT_NAME=nssf + volumes: + - ../../nssf:/mnt/nssf + - ../../log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${NSSF_IP} + metrics: + build: ../../metrics + image: docker_metrics + container_name: metrics + env_file: + - .custom_env + volumes: + - ../../metrics:/mnt/metrics + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9090/tcp" + ports: + - "9090:9090/tcp" + networks: + default: + ipv4_address: ${METRICS_IP} + dns: + build: ../../dns + image: docker_dns + container_name: dns + env_file: + - .custom_env + volumes: + - ../../dns:/mnt/dns + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "53/udp" + networks: + default: + ipv4_address: ${DNS_IP} + rtpengine: + build: ../../rtpengine + image: docker_rtpengine + container_name: rtpengine + privileged: true + env_file: + - .custom_env + volumes: + - ../../rtpengine:/mnt/rtpengine + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + cap_add: + - NET_ADMIN + environment: + - TABLE=0 + - INTERFACE=${RTPENGINE_IP} + - LISTEN_NG=${RTPENGINE_IP}:2223 + - PIDFILE=/run/ngcp-rtpengine-daemon.pid + - PORT_MAX=50000 + - PORT_MIN=49000 + - NO_FALLBACK=no + - TOS=184 + expose: + - "2223/udp" + - "49000-50000/udp" + networks: + default: + ipv4_address: ${RTPENGINE_IP} + mysql: + build: ../../mysql + image: docker_mysql + container_name: mysql + env_file: + - .custom_env + volumes: + - dbdata:/var/lib/mysql + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3306/tcp" + networks: + default: + ipv4_address: ${MYSQL_IP} + pyhss: + build: ../../pyhss + image: docker_pyhss + container_name: pyhss + dns: ${DNS_IP} + volumes: + - ../../pyhss:/mnt/pyhss + - ../../pyhss/logs:/pyhss/log/ + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + depends_on: + - dns + - mysql + expose: + - "${PYHSS_BIND_PORT}/tcp" + - "${PYHSS_BIND_PORT}/sctp" + - "8080/tcp" + ports: + - "8080:8080/tcp" + networks: + default: + ipv4_address: ${PYHSS_IP} + icscf: + image: docker_kamailio + container_name: icscf + dns: ${DNS_IP} + volumes: + - ../../icscf:/mnt/icscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=icscf + depends_on: + - dns + - mysql + - pyhss + expose: + - "${ICSCF_BIND_PORT}/tcp" + - "${ICSCF_BIND_PORT}/sctp" + - "4060/udp" + - "4060/tcp" + networks: + default: + ipv4_address: ${ICSCF_IP} + scscf: + image: docker_kamailio + container_name: scscf + dns: ${DNS_IP} + volumes: + - ../../scscf:/mnt/scscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=scscf + depends_on: + - dns + - mysql + - pyhss + expose: + - "${SCSCF_BIND_PORT}/tcp" + - "${SCSCF_BIND_PORT}/sctp" + - "6060/udp" + - "6060/tcp" + networks: + default: + ipv4_address: ${SCSCF_IP} + pcscf: + image: docker_kamailio + container_name: pcscf + dns: ${DNS_IP} + privileged: true + cap_add: + - NET_ADMIN + volumes: + - ../../pcscf:/mnt/pcscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=pcscf + - DEPLOY_MODE=5G + depends_on: + - dns + - mysql + - rtpengine + - icscf + - scscf + expose: + - "${PCSCF_BIND_PORT}/tcp" + - "${PCSCF_BIND_PORT}/sctp" + - "5060/tcp" + - "5060/udp" + - "5100-5120/tcp" + - "5100-5120/udp" + - "6100-6120/tcp" + - "6100-6120/udp" + networks: + default: + ipv4_address: ${PCSCF_IP} + smsc: + image: docker_kamailio + container_name: smsc + dns: ${DNS_IP} + volumes: + - ../../smsc:/mnt/smsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=smsc + depends_on: + - dns + - mysql + expose: + - "7090/udp" + - "7090/tcp" + networks: + default: + ipv4_address: ${SMSC_IP} + grafana: + image: grafana/grafana:11.3.0 + container_name: grafana + env_file: + - .custom_env + volumes: + - grafana_data:/var/lib/grafana + - ../../grafana/:/etc/grafana/provisioning/ + - ../../grafana:/mnt/grafana + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} + #- GF_INSTALL_PLUGINS=${GRAFANA_INSTALL_PLUGINS} + - GF_PATHS_PROVISIONING=/etc/grafana/provisioning + - GF_PATHS_DATA=/var/lib/grafana + - METRICS_IP=${METRICS_IP} + expose: + - "3000/tcp" + ports: + - "3000:3000/tcp" + networks: + default: + ipv4_address: ${GRAFANA_IP} +networks: + default: + name: docker_open5gs_default + ipam: + config: + - subnet: ${TEST_NETWORK} +volumes: + grafana_data: + name: grafana_data + mongodbdata: + name: docker_open5gs_mongodbdata + dbdata: + name: docker_open5gs_dbdata diff --git a/custom_deployments/with_eupf/srsgnb.yaml b/custom_deployments/with_eupf/srsgnb.yaml new file mode 100644 index 0000000..368b456 --- /dev/null +++ b/custom_deployments/with_eupf/srsgnb.yaml @@ -0,0 +1,30 @@ +version: '3' +services: + srsgnb: + image: docker_srsran + container_name: srsgnb + stdin_open: true + tty: true + privileged: true + devices: + - "/dev/bus" + volumes: + - /dev/serial:/dev/serial:ro + - /dev/bus/usb:/dev/bus/usb:ro + - ../../srsran:/mnt/srsran + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=gnb + expose: + - "38412/sctp" + - "2152/udp" + networks: + default: + ipv4_address: ${SRS_GNB_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/custom_deployments/with_eupf/srsgnb_zmq.yaml b/custom_deployments/with_eupf/srsgnb_zmq.yaml new file mode 100644 index 0000000..72fff13 --- /dev/null +++ b/custom_deployments/with_eupf/srsgnb_zmq.yaml @@ -0,0 +1,28 @@ +version: '3' +services: + srsgnb_zmq: + image: docker_srsran + container_name: srsgnb_zmq + stdin_open: true + tty: true + privileged: true + volumes: + - ../../srsran:/mnt/srsran + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=gnb_zmq + expose: + - "38412/sctp" + - "2152/udp" + - "2000/tcp" + - "2001/tcp" + networks: + default: + ipv4_address: ${SRS_GNB_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/custom_deployments/with_eupf/srsue_5g_zmq.yaml b/custom_deployments/with_eupf/srsue_5g_zmq.yaml new file mode 100644 index 0000000..d9e8839 --- /dev/null +++ b/custom_deployments/with_eupf/srsue_5g_zmq.yaml @@ -0,0 +1,28 @@ +version: '3' +services: + srsue_5g_zmq: + image: docker_srslte + container_name: srsue_5g_zmq + stdin_open: true + tty: true + cap_add: + - NET_ADMIN + privileged: true + volumes: + - ../../srslte:/mnt/srslte + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .custom_env + environment: + - COMPONENT_NAME=ue_5g_zmq + expose: + - "2000/tcp" + - "2001/tcp" + networks: + default: + ipv4_address: ${SRS_UE_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/deploy-all.yaml b/deploy-all.yaml new file mode 100644 index 0000000..b428eb3 --- /dev/null +++ b/deploy-all.yaml @@ -0,0 +1,712 @@ +services: + mongo: + image: mongo:6.0 + container_name: mongo + command: --bind_ip 0.0.0.0 + env_file: + - .env + volumes: + - mongodbdata:/data/db + - mongodbdata:/data/configdb + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "27017/udp" + - "27017/tcp" + networks: + default: + ipv4_address: ${MONGO_IP} + webui: + image: docker_open5gs + container_name: webui + depends_on: + - mongo + env_file: + - .env + environment: + - COMPONENT_NAME=webui + volumes: + - ./webui:/mnt/webui + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9999/tcp" + ports: + - "9999:9999/tcp" + networks: + default: + ipv4_address: ${WEBUI_IP} + nrf: + image: docker_open5gs + container_name: nrf + env_file: + - .env + environment: + - COMPONENT_NAME=nrf + volumes: + - ./nrf:/mnt/nrf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${NRF_IP} + scp: + image: docker_open5gs + depends_on: + - nrf + container_name: scp + env_file: + - .env + environment: + - COMPONENT_NAME=scp + volumes: + - ./scp:/mnt/scp + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${SCP_IP} + ausf: + image: docker_open5gs + depends_on: + - nrf + - scp + container_name: ausf + env_file: + - .env + environment: + - COMPONENT_NAME=ausf + volumes: + - ./ausf:/mnt/ausf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${AUSF_IP} + udr: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: udr + env_file: + - .env + environment: + - COMPONENT_NAME=udr + volumes: + - ./udr:/mnt/udr + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${UDR_IP} + udm: + image: docker_open5gs + depends_on: + - nrf + - scp + container_name: udm + env_file: + - .env + environment: + - COMPONENT_NAME=udm + volumes: + - ./udm:/mnt/udm + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${UDM_IP} + pcf: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: pcf + env_file: + - .env + environment: + - COMPONENT_NAME=pcf + volumes: + - ./pcf:/mnt/pcf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${PCF_IP} + bsf: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: bsf + env_file: + - .env + environment: + - COMPONENT_NAME=bsf + volumes: + - ./bsf:/mnt/bsf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${BSF_IP} + nssf: + image: docker_open5gs + depends_on: + - nrf + - scp + - mongo + container_name: nssf + env_file: + - .env + environment: + - COMPONENT_NAME=nssf + volumes: + - ./nssf:/mnt/nssf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "7777/tcp" + networks: + default: + ipv4_address: ${NSSF_IP} + hss: + image: docker_open5gs + container_name: hss + env_file: + - .env + environment: + - COMPONENT_NAME=hss + volumes: + - ./hss:/mnt/hss + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + depends_on: + - mongo + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + networks: + default: + ipv4_address: ${HSS_IP} + sgwc: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwc + env_file: + - .env + environment: + - COMPONENT_NAME=sgwc + volumes: + - ./sgwc:/mnt/sgwc + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2123/udp" + - "8805/udp" + networks: + default: + ipv4_address: ${SGWC_IP} + sgwu: + image: docker_open5gs + depends_on: + - smf + - upf + container_name: sgwu + env_file: + - .env + environment: + - COMPONENT_NAME=sgwu + volumes: + - ./sgwu:/mnt/sgwu + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "8805/udp" + - "2152/udp" + # ports: + # - "2152:2152/udp" + networks: + default: + ipv4_address: ${SGWU_IP} + smf: + image: docker_open5gs + depends_on: + - nrf + - scp + - amf + container_name: smf + env_file: + - .env + environment: + - COMPONENT_NAME=smf + - DEPLOY_MODE=ALL + volumes: + - ./smf:/mnt/smf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "8805/udp" + - "2123/udp" + - "7777/tcp" + - "9091/tcp" + networks: + default: + ipv4_address: ${SMF_IP} + upf: + image: docker_open5gs + depends_on: + - nrf + - scp + - smf + container_name: upf + env_file: + - .env + environment: + - COMPONENT_NAME=upf + volumes: + - ./upf:/mnt/upf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2152/udp" + - "8805/udp" + - "9091/tcp" + # ports: + # - "2152:2152/udp" + cap_add: + - NET_ADMIN + privileged: true + sysctls: + - net.ipv4.ip_forward=1 + #- net.ipv6.conf.all.disable_ipv6=0 + networks: + default: + ipv4_address: ${UPF_IP} + amf: + image: docker_open5gs + depends_on: + - nrf + - scp + - ausf + - udm + - udr + - pcf + - bsf + container_name: amf + env_file: + - .env + environment: + - COMPONENT_NAME=amf + volumes: + - ./amf:/mnt/amf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "38412/sctp" + - "7777/tcp" + - "9091/tcp" + # ports: + # - "38412:38412/sctp" + networks: + default: + ipv4_address: ${AMF_IP} + mme: + image: docker_open5gs + depends_on: + - hss + - sgwc + - sgwu + - smf + - upf + - osmomsc + container_name: mme + env_file: + - .env + environment: + - COMPONENT_NAME=mme + volumes: + - ./mme:/mnt/mme + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/tcp" + - "3868/sctp" + - "5868/tcp" + - "5868/sctp" + - "36412/sctp" + - "2123/udp" + - "9091/tcp" + # ports: + # - "36412:36412/sctp" + networks: + default: + ipv4_address: ${MME_IP} + pcrf: + image: docker_open5gs + container_name: pcrf + env_file: + - .env + environment: + - COMPONENT_NAME=pcrf + depends_on: + - mongo + volumes: + - ./pcrf:/mnt/pcrf + - ./log:/open5gs/install/var/log/open5gs + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "${PCRF_BIND_PORT}/tcp" + - "${PCRF_BIND_PORT}/sctp" + - "5868/tcp" + - "5868/sctp" + networks: + default: + ipv4_address: ${PCRF_IP} + ocs: + build: ./ocs + image: docker_ocs + container_name: ocs + env_file: + - .env + environment: + - COMPONENT_NAME=ocs + depends_on: + - smf + volumes: + - ./ocs:/mnt/ocs + - ocsdbdata:/home/otp/db + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "${OCS_BIND_PORT}/tcp" + - "${OCS_BIND_PORT}/sctp" + - "8083/tcp" + ports: + - "8083:8083/tcp" + networks: + default: + ipv4_address: ${OCS_IP} + dns: + build: ./dns + image: docker_dns + container_name: dns + env_file: + - .env + volumes: + - ./dns:/mnt/dns + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "53/udp" + networks: + default: + ipv4_address: ${DNS_IP} + rtpengine: + build: ./rtpengine + image: docker_rtpengine + container_name: rtpengine + privileged: true + env_file: + - .env + volumes: + - ./rtpengine:/mnt/rtpengine + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + cap_add: + - NET_ADMIN + environment: + - TABLE=0 + - INTERFACE=${RTPENGINE_IP} + - LISTEN_NG=${RTPENGINE_IP}:2223 + - PIDFILE=/run/ngcp-rtpengine-daemon.pid + - PORT_MAX=50000 + - PORT_MIN=49000 + - NO_FALLBACK=no + - TOS=184 + expose: + - "2223/udp" + - "49000-50000/udp" + networks: + default: + ipv4_address: ${RTPENGINE_IP} + mysql: + build: ./mysql + image: docker_mysql + container_name: mysql + env_file: + - .env + volumes: + - dbdata:/var/lib/mysql + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3306/tcp" + networks: + default: + ipv4_address: ${MYSQL_IP} + pyhss: + build: ./pyhss + image: docker_pyhss + container_name: pyhss + dns: ${DNS_IP} + volumes: + - ./pyhss:/mnt/pyhss + - ./pyhss/logs:/pyhss/log/ + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + depends_on: + - dns + - mysql + expose: + - "${PYHSS_BIND_PORT}/tcp" + - "${PYHSS_BIND_PORT}/sctp" + - "8080/tcp" + ports: + - "8080:8080/tcp" + networks: + default: + ipv4_address: ${PYHSS_IP} + icscf: + image: docker_kamailio + container_name: icscf + dns: ${DNS_IP} + volumes: + - ./icscf:/mnt/icscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=icscf + depends_on: + - dns + - mysql + - pyhss + expose: + - "${ICSCF_BIND_PORT}/tcp" + - "${ICSCF_BIND_PORT}/sctp" + - "4060/udp" + - "4060/tcp" + networks: + default: + ipv4_address: ${ICSCF_IP} + scscf: + image: docker_kamailio + container_name: scscf + dns: ${DNS_IP} + volumes: + - ./scscf:/mnt/scscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=scscf + depends_on: + - dns + - mysql + - pyhss + expose: + - "${SCSCF_BIND_PORT}/tcp" + - "${SCSCF_BIND_PORT}/sctp" + - "6060/udp" + - "6060/tcp" + networks: + default: + ipv4_address: ${SCSCF_IP} + pcscf: + image: docker_kamailio + container_name: pcscf + dns: ${DNS_IP} + privileged: true + cap_add: + - NET_ADMIN + volumes: + - ./pcscf:/mnt/pcscf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=pcscf + - DEPLOY_MODE=ALL + depends_on: + - dns + - mysql + - rtpengine + - icscf + - scscf + expose: + - "${PCSCF_BIND_PORT}/tcp" + - "${PCSCF_BIND_PORT}/sctp" + - "5060/tcp" + - "5060/udp" + - "5100-5120/tcp" + - "5100-5120/udp" + - "6100-6120/tcp" + - "6100-6120/udp" + networks: + default: + ipv4_address: ${PCSCF_IP} + smsc: + image: docker_kamailio + container_name: smsc + dns: ${DNS_IP} + volumes: + - ./smsc:/mnt/smsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=smsc + depends_on: + - dns + - mysql + expose: + - "7090/udp" + - "7090/tcp" + networks: + default: + ipv4_address: ${SMSC_IP} + osmomsc: + build: ./osmomsc + image: docker_osmomsc + container_name: osmomsc + volumes: + - ./osmomsc:/mnt/osmomsc + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=osmomsc + depends_on: + - osmohlr + expose: + - "29118/sctp" + - "2775/tcp" + networks: + default: + ipv4_address: ${OSMOMSC_IP} + osmohlr: + build: ./osmohlr + image: docker_osmohlr + container_name: osmohlr + volumes: + - ./osmohlr:/mnt/osmohlr + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=osmohlr + expose: + - "4222/tcp" + networks: + default: + ipv4_address: ${OSMOHLR_IP} + metrics: + build: ./metrics + image: docker_metrics + container_name: metrics + env_file: + - .env + volumes: + - ./metrics:/mnt/metrics + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "9090/tcp" + ports: + - "9090:9090/tcp" + networks: + default: + ipv4_address: ${METRICS_IP} + grafana: + image: grafana/grafana:11.3.0 + container_name: grafana + env_file: + - .env + volumes: + - grafana_data:/var/lib/grafana + - ./grafana/:/etc/grafana/provisioning/ + - ./grafana:/mnt/grafana + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USERNAME} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} + #- GF_INSTALL_PLUGINS=${GRAFANA_INSTALL_PLUGINS} + - GF_PATHS_PROVISIONING=/etc/grafana/provisioning + - GF_PATHS_DATA=/var/lib/grafana + - METRICS_IP=${METRICS_IP} + expose: + - "3000/tcp" + ports: + - "3000:3000/tcp" + networks: + default: + ipv4_address: ${GRAFANA_IP} +networks: + default: + name: docker_open5gs_default + ipam: + config: + - subnet: ${TEST_NETWORK} +volumes: + grafana_data: + name: grafana_data + mongodbdata: + name: docker_open5gs_mongodbdata + dbdata: + name: docker_open5gs_dbdata + ocsdbdata: + name: docker_open5gs_ocsdbdata + diff --git a/dns/Dockerfile b/dns/Dockerfile new file mode 100644 index 0000000..f6354f0 --- /dev/null +++ b/dns/Dockerfile @@ -0,0 +1,37 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM ubuntu:focal + +ENV DEBIAN_FRONTEND=noninteractive + +# Install updates and dependencies +RUN apt-get update && \ + apt-get -y install tcpdump screen tmux ntp ntpdate iproute2 net-tools \ + iputils-ping bind9 + +CMD /mnt/dns/dns_init.sh && \ + /usr/sbin/named -c /etc/bind/named.conf -g -u bind diff --git a/dns/dns_init.sh b/dns/dns_init.sh new file mode 100755 index 0000000..1c769f7 --- /dev/null +++ b/dns/dns_init.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +cp /mnt/dns/epc_zone /etc/bind +cp /mnt/dns/ims_zone /etc/bind +cp /mnt/dns/pub_3gpp_zone /etc/bind +cp /mnt/dns/e164.arpa /etc/bind +cp /mnt/dns/named.conf /etc/bind + +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" +[ ${#MNC} == 3 ] && PUB_3GPP_DOMAIN="mnc${MNC}.mcc${MCC}.pub.3gppnetwork.org" || PUB_3GPP_DOMAIN="mnc0${MNC}.mcc${MCC}.pub.3gppnetwork.org" + +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/bind/epc_zone +sed -i 's|DNS_IP|'$DNS_IP'|g' /etc/bind/epc_zone +[ -z "$PCRF_PUB_IP" ] && sed -i 's|PCRF_IP|'$PCRF_IP'|g' /etc/bind/epc_zone || sed -i 's|PCRF_IP|'$PCRF_PUB_IP'|g' /etc/bind/epc_zone + +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/bind/ims_zone +sed -i 's|DNS_IP|'$DNS_IP'|g' /etc/bind/ims_zone +sed -i 's|PCSCF_IP|'$PCSCF_IP'|g' /etc/bind/ims_zone +sed -i 's|ICSCF_IP|'$ICSCF_IP'|g' /etc/bind/ims_zone +sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' /etc/bind/ims_zone +sed -i 's|PYHSS_IP|'$PYHSS_IP'|g' /etc/bind/ims_zone +sed -i 's|SMSC_IP|'$SMSC_IP'|g' /etc/bind/ims_zone +sed -i 's|IBCF_IP|'$IBCF_IP'|g' /etc/bind/ims_zone + +sed -i 's|PUB_3GPP_DOMAIN|'$PUB_3GPP_DOMAIN'|g' /etc/bind/pub_3gpp_zone +sed -i 's|DNS_IP|'$DNS_IP'|g' /etc/bind/pub_3gpp_zone +sed -i 's|ENTITLEMENT_SERVER_IP|'$ENTITLEMENT_SERVER_IP'|g' /etc/bind/pub_3gpp_zone + +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/bind/e164.arpa +sed -i 's|DNS_IP|'$DNS_IP'|g' /etc/bind/e164.arpa + +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/bind/named.conf +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/bind/named.conf +sed -i 's|PUB_3GPP_DOMAIN|'$PUB_3GPP_DOMAIN'|g' /etc/bind/named.conf + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/dns/e164.arpa b/dns/e164.arpa new file mode 100644 index 0000000..cda832f --- /dev/null +++ b/dns/e164.arpa @@ -0,0 +1,17 @@ +$TTL 1h +@ IN SOA ns.e164.arpa. root.e164.arpa. ( + 2009010918 ;serial + 3600 ;refresh + 3600 ;retry + 3600 ;expire + 3600 ;minimum TTL +) +@ IN NS e164.arpa. +@ IN A DNS_IP + +; Wildcard to match any tel:+xxxx and change to sip:xxxx@IMS_DOMAIN +* IN NAPTR 10 100 "u" "E2U+sip" "!(^.*$)!sip:\\1@IMS_DOMAIN!" . +; Record to route calls starting with DE +49 to IBCF : +*.9.4 IN NAPTR 20 100 "u" "E2U+sip" "!(^.*$)!sip:\\1@ibcf.IMS_DOMAIN!" . +; Add more country codes to route over IBCF using the same format as below. You may need also to adjust the dialplan in Asterisk, e.g. for UK +44: +; *.4.4 IN NAPTR 20 100 "u" "E2U+sip" "!(^.*$)!sip:\\1@ibcf.IMS_DOMAIN!" . diff --git a/dns/epc_zone b/dns/epc_zone new file mode 100644 index 0000000..b6acfe7 --- /dev/null +++ b/dns/epc_zone @@ -0,0 +1,13 @@ +$ORIGIN EPC_DOMAIN. +$TTL 1W +@ 1D IN SOA localhost. root.localhost. ( + 1 ; serial + 3H ; refresh + 15M ; retry + 1W ; expiry + 1D ) ; minimum + + 1D IN NS epcns +epcns 1D IN A DNS_IP + +pcrf 1D IN A PCRF_IP diff --git a/dns/ims_zone b/dns/ims_zone new file mode 100644 index 0000000..a1697e2 --- /dev/null +++ b/dns/ims_zone @@ -0,0 +1,37 @@ +$ORIGIN IMS_DOMAIN. +$TTL 1W +@ 1D IN SOA localhost. root.localhost. ( + 1 ; serial + 3H ; refresh + 15M ; retry + 1W ; expiry + 1D ) ; minimum + + 1D IN NS ns +ns 1D IN A DNS_IP + +pcscf 1D IN A PCSCF_IP +_sip._udp.pcscf 1D SRV 0 0 5060 pcscf +_sip._tcp.pcscf 1D SRV 0 0 5060 pcscf + +icscf 1D IN A ICSCF_IP +_sip._udp 1D SRV 0 0 4060 icscf +_sip._tcp 1D SRV 0 0 4060 icscf + +scscf 1D IN A SCSCF_IP +_sip._udp.scscf 1D SRV 0 0 6060 scscf +_sip._tcp.scscf 1D SRV 0 0 6060 scscf + +hss 1D IN A PYHSS_IP + +smsc 1D IN A SMSC_IP +_sip._udp.smsc 1D SRV 0 0 7090 smsc +_sip._tcp.smsc 1D SRV 0 0 7090 smsc + +ibcf 1D IN A IBCF_IP +_sip._udp.ibcf 1D SRV 0 0 5090 ibcf +_sip._tcp.ibcf 1D SRV 0 0 5090 ibcf + +voicemail 1D IN A IBCF_IP +_sip._udp.voicemail 1D SRV 0 0 5090 voicemail +_sip._tcp.voicemail 1D SRV 0 0 5090 voicemail diff --git a/dns/named.conf b/dns/named.conf new file mode 100644 index 0000000..a6ed6ab --- /dev/null +++ b/dns/named.conf @@ -0,0 +1,53 @@ +options { + directory "/var/cache/bind"; + + // If there is a firewall between you and nameservers you want + // to talk to, you may need to fix the firewall to allow multiple + // ports to talk. See http://www.kb.cert.org/vuls/id/800113 + + // If your ISP provided one or more IP addresses for stable + // nameservers, you probably want to use them as forwarders. + // Uncomment the following block, and insert the addresses replacing + // the all-0's placeholder. + + forwarders { + 8.8.8.8; + }; + + //======================================================================== + // If BIND logs error messages about the root key being expired, + // you will need to update your keys. See https://www.isc.org/bind-keys + //======================================================================== + dnssec-validation no; + allow-query { any; }; + + auth-nxdomain no; # conform to RFC1035 + listen-on-v6 { any; }; +}; + +// +// Do any local configuration here +// + +// Consider adding the 1918 zones here, if they are not used in your +// organization +//include "/etc/bind/zones.rfc1918"; +zone "IMS_DOMAIN" { + type master; + file "/etc/bind/ims_zone"; +}; + +zone "EPC_DOMAIN" { + type master; + file "/etc/bind/epc_zone"; +}; + +zone "PUB_3GPP_DOMAIN" { + type master; + file "/etc/bind/pub_3gpp_zone"; +}; + +zone "e164.arpa" { + type master; + file "/etc/bind/e164.arpa"; +}; diff --git a/dns/pub_3gpp_zone b/dns/pub_3gpp_zone new file mode 100644 index 0000000..e7b27bc --- /dev/null +++ b/dns/pub_3gpp_zone @@ -0,0 +1,13 @@ +$ORIGIN PUB_3GPP_DOMAIN. +$TTL 1W +@ 1D IN SOA localhost. root.localhost. ( + 1 ; serial + 3H ; refresh + 15M ; retry + 1W ; expiry + 1D ) ; minimum + + 1D IN NS pubns +pubns 1D IN A DNS_IP + +aes 1D IN A ENTITLEMENT_SERVER_IP diff --git a/eupf/Dockerfile b/eupf/Dockerfile new file mode 100644 index 0000000..51598ba --- /dev/null +++ b/eupf/Dockerfile @@ -0,0 +1,55 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM ubuntu:jammy + +ENV DEBIAN_FRONTEND=noninteractive + +# Install updates and dependencies +RUN apt-get update && \ + apt-get -y install wget git clang llvm gcc-multilib libbpf-dev \ + net-tools iputils-ping git ifupdown iperf iptables + +# Install Golang +RUN rm -rf /usr/local/go && wget https://go.dev/dl/go1.22.4.linux-amd64.tar.gz && \ + tar -C /usr/local -xzf go1.22.4.linux-amd64.tar.gz + +ENV PATH="/usr/local/go/bin:${PATH}" + +# Install the Swag command line tool for Golang +RUN go install github.com/swaggo/swag/cmd/swag@v1.8.12 + +# Get eupf, compile and install +RUN export PATH=$(go env GOPATH)/bin:${PATH} && \ + git clone https://github.com/edgecomllc/eupf.git && \ + cd eupf && git checkout tags/v0.6.4 && \ + go generate -v ./cmd/... && \ + go build -v -o bin/eupf ./cmd/ + +# Set the working directory to eupf +WORKDIR eupf + +CMD /mnt/eupf/eupf_init.sh diff --git a/eupf/eupf_init.sh b/eupf/eupf_init.sh new file mode 100755 index 0000000..220bbd6 --- /dev/null +++ b/eupf/eupf_init.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export PATH="/usr/local/go/bin:${PATH}" +export PATH=$(go env GOPATH)/bin:${PATH} +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) +export IF_NAME=$(ip r | awk '/default/ { print $5 }') + +exec ./bin/eupf \ + --iface $IF_NAME \ + --aaddr $UPF_IP:8181 \ + --paddr $UPF_IP:8805 \ + --maddr $UPF_IP:9091 \ + --nodeid $UPF_IP \ + --ueip false \ + --ftup false \ + --loglvl info \ + --n3addr $UPF_ADVERTISE_IP $@ + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/grafana/dashboards/open5gs_dashboard.json b/grafana/dashboards/open5gs_dashboard.json new file mode 100644 index 0000000..5a78165 --- /dev/null +++ b/grafana/dashboards/open5gs_dashboard.json @@ -0,0 +1,452 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "PA240B69645956401" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PA240B69645956401" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "fivegs_ep_n3_gtp_indatapktn3upf", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "PA240B69645956401" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "fivegs_ep_n3_gtp_outdatapktn3upf", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "B", + "useBackend": false + } + ], + "title": "UPF - GTP Packets", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PA240B69645956401" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PA240B69645956401" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "fivegs_upffunction_upf_sessionnbr", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "UPF - Active Sessions", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PA240B69645956401" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PA240B69645956401" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "enb", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "MME - eNBs", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PA240B69645956401" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PA240B69645956401" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "enb_ue", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "MME - Sessions", + "type": "timeseries" + } + ], + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Open5Gs", + "uid": "fdg9t0npkjj7ka", + "version": 1, + "weekStart": "" +} diff --git a/grafana/dashboards/open5gs_dashboard.yml b/grafana/dashboards/open5gs_dashboard.yml new file mode 100644 index 0000000..8bf7ffc --- /dev/null +++ b/grafana/dashboards/open5gs_dashboard.yml @@ -0,0 +1,8 @@ +apiVersion: 1 + +providers: + - name: Open5Gs # A uniquely identifiable name for the provider + folder: Services # The folder where to place the dashboards + type: file + options: + path: /etc/grafana/provisioning/dashboards diff --git a/grafana/datasources/prometheus_open5gs.yml b/grafana/datasources/prometheus_open5gs.yml new file mode 100644 index 0000000..03b3ac5 --- /dev/null +++ b/grafana/datasources/prometheus_open5gs.yml @@ -0,0 +1,9 @@ +apiVersion: 1 + +datasources: + - name: Open5Gs + type: prometheus + access: proxy + url: http://${METRICS_IP}:9090 + disableDeletion: false + editable: true \ No newline at end of file diff --git a/hss/hss.conf b/hss/hss.conf new file mode 100644 index 0000000..d0422e3 --- /dev/null +++ b/hss/hss.conf @@ -0,0 +1,264 @@ +# This is a sample configuration file for freeDiameter daemon. + +# Most of the options can be omitted, as they default to reasonable values. +# Only TLS-related options must be configured properly in usual setups. + +# It is possible to use "include" keyword to import additional files +# e.g.: include "/etc/freeDiameter.d/*.conf" +# This is exactly equivalent as copy & paste the content of the included file(s) +# where the "include" keyword is found. + + +############################################################## +## Peer identity and realm + +# The Diameter Identity of this daemon. +# This must be a valid FQDN that resolves to the local host. +# Default: hostname's FQDN +#Identity = "aaa.koganei.freediameter.net"; +Identity = "hss.EPC_DOMAIN"; + +# The Diameter Realm of this daemon. +# Default: the domain part of Identity (after the first dot). +#Realm = "koganei.freediameter.net"; +Realm = "EPC_DOMAIN"; + +############################################################## +## Transport protocol configuration + +# The port this peer is listening on for incoming connections (TCP and SCTP). +# Default: 3868. Use 0 to disable. +#Port = 3868; + +# The port this peer is listening on for incoming TLS-protected connections (TCP and SCTP). +# See TLS_old_method for more information about TLS flavours. +# Note: we use TLS/SCTP instead of DTLS/SCTP at the moment. This will change in future version of freeDiameter. +# Default: 5868. Use 0 to disable. +#SecPort = 5868; + +# Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA exchange is completed +# on the unsecure connection. The alternative is RFC6733 mechanism, where TLS protects also the +# CER/CEA exchange on a dedicated secure port. +# This parameter only affects outgoing connections. +# The setting can be also defined per-peer (see Peers configuration section). +# Default: use RFC6733 method with separate port for TLS. +#TLS_old_method; + +# Disable use of TCP protocol (only listen and connect over SCTP) +# Default : TCP enabled +#No_TCP; + +# Disable use of SCTP protocol (only listen and connect over TCP) +# Default : SCTP enabled +#No_SCTP; +# This option is ignored if freeDiameter is compiled with DISABLE_SCTP option. + +# Prefer TCP instead of SCTP for establishing new connections. +# This setting may be overwritten per peer in peer configuration blocs. +# Default : SCTP is attempted first. +#Prefer_TCP; + +# Default number of streams per SCTP associations. +# This setting may be overwritten per peer basis. +# Default : 30 streams +#SCTP_streams = 30; + +############################################################## +## Endpoint configuration + +# Disable use of IP addresses (only IPv6) +# Default : IP enabled +#No_IP; + +# Disable use of IPv6 addresses (only IP) +# Default : IPv6 enabled +#No_IPv6; + +# Specify local addresses the server must bind to +# Default : listen on all addresses available. +#ListenOn = "202.249.37.5"; +#ListenOn = "2001:200:903:2::202:1"; +#ListenOn = "fe80::21c:5ff:fe98:7d62%eth0"; +ListenOn = "HSS_IP"; + +############################################################## +## Server configuration + +# How many Diameter peers are allowed to be connecting at the same time ? +# This parameter limits the number of incoming connections from the time +# the connection is accepted until the first CER is received. +# Default: 5 unidentified clients in paralel. +#ThreadsPerServer = 5; + +############################################################## +## TLS Configuration + +# TLS is managed by the GNUTLS library in the freeDiameter daemon. +# You may find more information about parameters and special behaviors +# in the relevant documentation. +# http://www.gnu.org/software/gnutls/manual/ + +# Credentials of the local peer +# The X509 certificate and private key file to use for the local peer. +# The files must contain PKCS-1 encoded RSA key, in PEM format. +# (These parameters are passed to gnutls_certificate_set_x509_key_file function) +# Default : NO DEFAULT +#TLS_Cred = "" , ""; +#TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key"; +TLS_Cred = "/open5gs/install/etc/freeDiameter/hss.cert.pem", "/open5gs/install/etc/freeDiameter/hss.key.pem"; + +# Certificate authority / trust anchors +# The file containing the list of trusted Certificate Authorities (PEM list) +# (This parameter is passed to gnutls_certificate_set_x509_trust_file function) +# The directive can appear several times to specify several files. +# Default : GNUTLS default behavior +#TLS_CA = ""; +TLS_CA = "/open5gs/install/etc/freeDiameter/cacert.pem"; + +# Certificate Revocation List file +# The information about revoked certificates. +# The file contains a list of trusted CRLs in PEM format. They should have been verified before. +# (This parameter is passed to gnutls_certificate_set_x509_crl_file function) +# Note: openssl CRL format might have interoperability issue with GNUTLS format. +# Default : GNUTLS default behavior +#TLS_CRL = ""; + +# GNU TLS Priority string +# This string allows to configure the behavior of GNUTLS key exchanges +# algorithms. See gnutls_priority_init function documentation for information. +# You should also refer to the Diameter required TLS support here: +# http://tools.ietf.org/html/rfc6733#section-13.1 +# Default : "NORMAL" +# Example: TLS_Prio = "NONE:+VERS-TLS1.1:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL"; +#TLS_Prio = "NORMAL"; + +# Diffie-Hellman parameters size +# Set the number of bits for generated DH parameters +# Valid value should be 768, 1024, 2048, 3072 or 4096. +# (This parameter is passed to gnutls_dh_params_generate2 function, +# it usually should match RSA key size) +# Default : 1024 +#TLS_DH_Bits = 1024; + +# Alternatively, you can specify a file to load the PKCS#3 encoded +# DH parameters directly from. This accelerates the daemon start +# but is slightly less secure. If this file is provided, the +# TLS_DH_Bits parameters has no effect. +# Default : no default. +#TLS_DH_File = ""; + + +############################################################## +## Timers configuration + +# The Tc timer of this peer. +# It is the delay before a new attempt is made to reconnect a disconnected peer. +# The value is expressed in seconds. The recommended value is 30 seconds. +# Default: 30 +#TcTimer = 30; + +# The Tw timer of this peer. +# It is the delay before a watchdog message is sent, as described in RFC 3539. +# The value is expressed in seconds. The default value is 30 seconds. Value must +# be greater or equal to 6 seconds. See details in the RFC. +# Default: 30 +#TwTimer = 30; + +############################################################## +## Applications configuration + +# Disable the relaying of Diameter messages? +# For messages not handled locally, the default behavior is to forward the +# message to another peer if any is available, according to the routing +# algorithms. In addition the "0xffffff" application is advertised in CER/CEA +# exchanges. +# Default: Relaying is enabled. +NoRelay; + +# Number of server threads that can handle incoming messages at the same time. +# Default: 4 +#AppServThreads = 4; + +# Other applications are configured by loaded extensions. + +############################################################## +## Extensions configuration + +# The freeDiameter framework merely provides support for +# Diameter Base Protocol. The specific application behaviors, +# as well as advanced functions, are provided +# by loadable extensions (plug-ins). +# These extensions may in addition receive the name of a +# configuration file, the format of which is extension-specific. +# +# Format: +#LoadExtension = "/path/to/extension" [ : "/optional/configuration/file" ] ; +# +# Examples: +#LoadExtension = "extensions/sample.fdx"; +#LoadExtension = "extensions/sample.fdx":"conf/sample.conf"; + +# Extensions are named as follow: +# dict_* for extensions that add content to the dictionary definitions. +# dbg_* for extensions useful only to retrieve more information on the framework execution. +# acl_* : Access control list, to control which peers are allowed to connect. +# rt_* : routing extensions that impact how messages are forwarded to other peers. +# app_* : applications, these extensions usually register callbacks to handle specific messages. +# test_* : dummy extensions that are useful only in testing environments. + + +# The dbg_msg_dump.fdx extension allows you to tweak the way freeDiameter displays some +# information about some events. This extension does not actually use a configuration file +# but receives directly a parameter in the string passed to the extension. Here are some examples: +## LoadExtension = "dbg_msg_dumps.fdx" : "0x1111"; # Removes all default hooks, very quiet even in case of errors. +## LoadExtension = "dbg_msg_dumps.fdx" : "0x2222"; # Display all events with few details. +## LoadExtension = "dbg_msg_dumps.fdx" : "0x0080"; # Dump complete information about sent and received messages. +# The four digits respectively control: connections, routing decisions, sent/received messages, errors. +# The values for each digit are: +# 0 - default - keep the default behavior +# 1 - quiet - remove any specific log +# 2 - compact - display only a summary of the information +# 4 - full - display the complete information on a single long line +# 8 - tree - display the complete information in an easier to read format spanning several lines. + +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dbg_msg_dumps.fdx" : "0x8888"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_rfc5777.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_mip6i.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_nasreq.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_nas_mipv6.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_dcca.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_dcca_3gpp.fdx"; + + +############################################################## +## Peers configuration + +# The local server listens for incoming connections. By default, +# all unknown connecting peers are rejected. Extensions can override this behavior (e.g., acl_wl). +# +# In addition to incoming connections, the local peer can +# be configured to establish and maintain connections to some +# Diameter nodes and allow connections from these nodes. +# This is achieved with the ConnectPeer directive described below. +# +# Note that the configured Diameter Identity MUST match +# the information received inside CEA, or the connection will be aborted. +# +# Format: +#ConnectPeer = "diameterid" [ { parameter1; parameter2; ...} ] ; +# Parameters that can be specified in the peer's parameter list: +# No_TCP; No_SCTP; No_IP; No_IPv6; Prefer_TCP; TLS_old_method; +# No_TLS; # assume transparent security instead of TLS. DTLS is not supported yet (will change in future versions). +# Port = 5868; # The port to connect to +# TcTimer = 30; +# TwTimer = 30; +# ConnectTo = "202.249.37.5"; +# ConnectTo = "2001:200:903:2::202:1"; +# TLS_Prio = "NORMAL"; +# Realm = "realm.net"; # Reject the peer if it does not advertise this realm. +# Examples: +#ConnectPeer = "aaa.wide.ad.jp"; +#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; Port=3868; } ; +ConnectPeer = "mme.EPC_DOMAIN" { ConnectTo = "MME_IP"; Port = 3868; No_TLS; }; + +############################################################## diff --git a/hss/hss.yaml b/hss/hss.yaml new file mode 100644 index 0000000..1666fb6 --- /dev/null +++ b/hss/hss.yaml @@ -0,0 +1,12 @@ +db_uri: mongodb://MONGO_IP/open5gs + +logger: + file: + path: /open5gs/install/var/log/open5gs/hss.log + +global: + max: + ue: MAX_NUM_UE + +hss: + freeDiameter: /open5gs/install/etc/freeDiameter/hss.conf diff --git a/hss/hss_init.sh b/hss/hss_init.sh new file mode 100755 index 0000000..062597b --- /dev/null +++ b/hss/hss_init.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export DB_URI="mongodb://${MONGO_IP}/open5gs" + +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) + +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +ln -s /usr/bin/mongo /usr/bin/mongosh +sed -i "s|localhost|$MONGO_IP|" /open5gs/misc/db/open5gs-dbctl + +cp /mnt/hss/hss.yaml install/etc/open5gs +cp /mnt/hss/hss.conf install/etc/freeDiameter +cp /mnt/hss/make_certs.sh install/etc/freeDiameter + +sed -i 's|HSS_IP|'$HSS_IP'|g' install/etc/freeDiameter/hss.conf +sed -i 's|MME_IP|'$MME_IP'|g' install/etc/freeDiameter/hss.conf +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' install/etc/freeDiameter/hss.conf +sed -i 's|LD_LIBRARY_PATH|'$LD_LIBRARY_PATH'|g' install/etc/freeDiameter/hss.conf +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' install/etc/freeDiameter/make_certs.sh +sed -i 's|MONGO_IP|'$MONGO_IP'|g' install/etc/open5gs/hss.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/hss.yaml + +# Generate TLS certificates +./install/etc/freeDiameter/make_certs.sh install/etc/freeDiameter + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/hss/make_certs.sh b/hss/make_certs.sh new file mode 100755 index 0000000..2faa713 --- /dev/null +++ b/hss/make_certs.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +if [ 1 -ne $# ] +then + echo You must specify output directory : ./make_certs.sh ./freeDiameter + + exit; +fi + +rm -rf demoCA +mkdir demoCA +echo 01 > demoCA/serial +touch demoCA/index.txt.attr +touch demoCA/index.txt + +# Generate .rnd if it does not exist +openssl rand -out /root/.rnd -hex 256 + +# CA self certificate +openssl req -new -batch -x509 -days 3650 -nodes -newkey rsa:1024 -out $1/cacert.pem -keyout cakey.pem -subj /CN=ca.EPC_DOMAIN/C=KO/ST=Seoul/L=Nowon/O=Open5GS/OU=Tests + +#hss +openssl genrsa -out $1/hss.key.pem 1024 +openssl req -new -batch -out hss.csr.pem -key $1/hss.key.pem -subj /CN=hss.EPC_DOMAIN/C=KO/ST=Seoul/L=Nowon/O=Open5GS/OU=Tests +openssl ca -cert $1/cacert.pem -days 3650 -keyfile cakey.pem -in hss.csr.pem -out $1/hss.cert.pem -outdir . -batch + +rm -f 01.pem 02.pem 03.pem 04.pem +rm -f cakey.pem +rm -f hss.csr.pem diff --git a/ibcf/Dockerfile b/ibcf/Dockerfile new file mode 100644 index 0000000..16df86a --- /dev/null +++ b/ibcf/Dockerfile @@ -0,0 +1,90 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM debian:bullseye +# Install required packages +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y \ + lsb-release \ + ca-certificates \ + git \ + vim \ + wget \ + curl \ + openssh-server \ + net-tools \ + && apt-get clean +RUN apt --no-install-recommends --assume-yes install unzip autoconf automake build-essential pkg-config libedit-dev libjansson-dev libsqlite3-dev uuid-dev libxslt1-dev xmlstarlet \ + && apt clean + +# Download Asterisk source : +WORKDIR /usr/src +RUN git clone -b releases/22 https://github.com/asterisk/asterisk.git +# Adding EVS and AMR support +# First EVS +WORKDIR /usr/src/asterisk +# install additional DEBs required by Asterisk +RUN sh contrib/scripts/install_prereq install +RUN sh contrib/scripts/get_mp3_source.sh +RUN git clone https://github.com/NUCLEAR-WAR/asterisk-evs.git +RUN cp --verbose --recursive ./asterisk-evs*/* ./ +RUN patch -p0 <./codec_evs.patch +RUN wget www.etsi.org/deliver/etsi_ts/126400_126499/126443/16.01.00_60/ts_126443v160100p0.zip +RUN unzip -qq ts_126443v*.zip +RUN unzip -qq 26443-*-ANSI-C_source_code.zip +WORKDIR /usr/src/asterisk/c-code +RUN chmod +r ./lib_*/*.h +RUN mkdir /usr/include/3gpp-evs +RUN cp --verbose --target-directory=/usr/include/3gpp-evs ./lib_*/*.h +RUN DEBUG=0 RELEASE=1 CFLAGS='-DNDEBUG -fPIC' make +WORKDIR /usr/src/asterisk/c-code/build +RUN rm ./decoder.o +RUN cc -shared -o lib3gpp-evs.so *.o +RUN cp ./lib3gpp-evs.so /usr/lib/ +WORKDIR /usr/src/asterisk +RUN patch -p0 <./build_evs.patch +RUN patch -p0 <./force_limitations.patch + +# Now AMR +RUN apt --assume-yes install libopencore-amrnb-dev libopencore-amrwb-dev libvo-amrwbenc-dev +RUN wget github.com/traud/asterisk-amr/archive/master.zip +RUN unzip -qq master.zip +RUN rm master.zip +RUN cp --verbose --recursive ./asterisk-amr*/* ./ +RUN patch -p0 <./codec_amr.patch +RUN patch -p0 <./build_tools.patch + +# Run the bootstrap script to re-generate configure files and configure patched Asterisk: +RUN ./bootstrap.sh +RUN ./configure +COPY menuselect.makedeps . +COPY menuselect.makeopts . +RUN make && make install + +COPY config/* /etc/asterisk/ + +CMD ["/mnt/ibcf/start-asterisk.sh"] diff --git a/ibcf/README.md b/ibcf/README.md new file mode 100644 index 0000000..5018f26 --- /dev/null +++ b/ibcf/README.md @@ -0,0 +1,8 @@ +This is a basic IBCF based on Asterisk to handle calls from and to docker_open5gs. Following files needs to be adapted based on your deployment: + +- pjsip.conf +- acl.conf +- extensions.conf +- voiemail.conf + +Parameters to be adapted in the above files are mentioned in the comment in respective files. diff --git a/ibcf/config/acl.conf b/ibcf/config/acl.conf new file mode 100644 index 0000000..9d7c0ea --- /dev/null +++ b/ibcf/config/acl.conf @@ -0,0 +1 @@ +[ibcf_acl] diff --git a/ibcf/config/asterisk.conf b/ibcf/config/asterisk.conf new file mode 100644 index 0000000..ff66cee --- /dev/null +++ b/ibcf/config/asterisk.conf @@ -0,0 +1,13 @@ +[options] +; If we want to start Asterisk with a default verbosity for the verbose +; or debug logger channel types, then we use these settings (by default +; they are disabled). +;verbose = 5 +;debug = 2 + +; User and group to run asterisk as. NOTE: This will require changes to +; directory and device permissions. +;runuser = asterisk ; The user to run as. The default is root. +;rungroup = asterisk ; The group to run as. The default is root + +;defaultlanguage = es diff --git a/ibcf/config/cdr.conf b/ibcf/config/cdr.conf new file mode 100644 index 0000000..e8749e3 --- /dev/null +++ b/ibcf/config/cdr.conf @@ -0,0 +1,7 @@ +[general] +enable=yes + +[custom] +; We log the unique ID as it can be useful for troubleshooting any issues +; that arise. +loguniqueid=yes diff --git a/ibcf/config/cdr_custom.conf b/ibcf/config/cdr_custom.conf new file mode 100644 index 0000000..12ad24f --- /dev/null +++ b/ibcf/config/cdr_custom.conf @@ -0,0 +1,4 @@ +[mappings] +; Our CDR log will be written to /var/log/asterisk/cdr-custom/Master.csv +; with the following schema. +Master.csv => ${CSV_QUOTE(${CDR(clid)})},${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})},${CSV_QUOTE(${CDR(dcontext)})},${CSV_QUOTE(${CDR(channel)})},${CSV_QUOTE(${CDR(dstchannel)})},${CSV_QUOTE(${CDR(lastapp)})},${CSV_QUOTE(${CDR(lastdata)})},${CSV_QUOTE(${CDR(start)})},${CSV_QUOTE(${CDR(answer)})},${CSV_QUOTE(${CDR(end)})},${CSV_QUOTE(${CDR(duration)})},${CSV_QUOTE(${CDR(billsec)})},${CSV_QUOTE(${CDR(disposition)})},${CSV_QUOTE(${CDR(amaflags)})},${CSV_QUOTE(${CDR(accountcode)})},${CSV_QUOTE(${CDR(uniqueid)})},${CSV_QUOTE(${CDR(userfield)})},${CDR(sequence)} diff --git a/ibcf/config/confbridge.conf b/ibcf/config/confbridge.conf new file mode 100644 index 0000000..3a44e68 --- /dev/null +++ b/ibcf/config/confbridge.conf @@ -0,0 +1 @@ +; All conferences use default settings. This config must be present to load the confbridge application diff --git a/ibcf/config/extensions.conf b/ibcf/config/extensions.conf new file mode 100644 index 0000000..d38cf35 --- /dev/null +++ b/ibcf/config/extensions.conf @@ -0,0 +1,171 @@ +; extensions.conf - the Asterisk dial plan +; +; Static extension configuration file, used by +; the pbx_config module. This is where you configure all your +; inbound and outbound calls in Asterisk. +; +; This configuration file is reloaded +; - With the "dialplan reload" command in the CLI +; - With the "reload" command (that reloads everything) in the CLI + +; +; The "General" category is for certain variables. +; +[general] +; +; If static is set to no, or omitted, then the pbx_config will rewrite +; this file when extensions are modified. Remember that all comments +; made in the file will be lost when that happens. +; +; XXX Not yet implemented XXX +; +static=yes +; +; if static=yes and writeprotect=no, you can save dialplan by +; CLI command "dialplan save" too +; +writeprotect=yes +; +; If autofallthrough is set, then if an extension runs out of +; things to do, it will terminate the call with BUSY, CONGESTION +; or HANGUP depending on Asterisk's best guess. This is the default. +; +; If autofallthrough is not set, then if an extension runs out of +; things to do, Asterisk will wait for a new extension to be dialed +; (this is the original behavior of Asterisk 1.0 and earlier). +; +;autofallthrough=no +; +; +; +; If extenpatternmatchnew is set (true, yes, etc), then a new algorithm that uses +; Trie +extenpatternmatchnew=no +; +; If clearglobalvars is set, global variables will be cleared +; and reparsed on a dialplan reload, or Asterisk reload. +; +; If clearglobalvars is not set, then global variables will persist +; through reloads, and even if deleted from the extensions.conf or +; one of its included files, will remain set to the previous value. +; +; NOTE: A complication sets in, if you put your global variables into +; the AEL file, instead of the extensions.conf file. With clearglobalvars +; set, a "reload" will often leave the globals vars cleared, because it +; is not unusual to have extensions.conf (which will have no globals) +; load after the extensions.ael file (where the global vars are stored). +; So, with "reload" in this particular situation, first the AEL file will +; clear and then set all the global vars, then, later, when the extensions.conf +; file is loaded, the global vars are all cleared, and then not set, because +; they are not stored in the extensions.conf file. +; +clearglobalvars=yes +; +; User context is where entries from users.conf are registered. The +; default value is 'default' +; +userscontext=unspecified + +; Below are some of the defined variables that will be used in the dialplan, which needs to be adjusted to your need. +; Below a German Trunk is being used hence the prefix used is +49. Adjust this based on your country. This is used during incoming calls and is assumed that provider sends only E164 numbers. +[globals] +INTERNAL_DIAL_OPT=,30 +ENUM_PREFIX_FOR_DE=+49 + +; Below is the head number. This needs to be changed based on the number provided by your provider. The head number consists of 10 digits. We will cut the head number and normalize it before it enters the IMS Core. +; There are various names for head number like direct dial in, prefix numbers, etc. It's basically the number from your SIP Trunk Provider that can be extended by adding digits to it. + +PHONE_NR_HEAD=1234567890 + +; Don't change +ICP_OUT=ICP_LINK_out +ICP_IN=ims_core +; change to your provider's provided domain +SIPTRUNK_DOMAIN=PROVIDER_DOMAIN +; Don't change +IMS_CN_DOMAIN=IMS_DOMAIN +PAI_HEADER=P-Asserted-Identity +PPI_HEADER=P-Preferred-Identity +NO_FORK=Request-Disposition +P_HEADER=P-Early-Media +X_HEADER=P-MeinSipTrunk + +; Dialplan +; Below is an explanation about the process by which calls are sent to and received from (from outside world) the IMS Core. +; In "incoming" section below, an internal MSISDN (0912584710) assigned in the private network is being used. +; In real world deployments, a shared database is maintained by all operators in order to know to which specific operator the number belongs to. But in our case the network is private and our numbers are unknown to the outside world. So a trick is needed to make the calls work. This trick consists of combining the head number provided by SIP Trunk provider and the UE MSISDN as specified below: +; CC+HEADER_NUMBER+MSISDN = +49 228 1234567 0912584710 and then cut or add the CC+HEADER_NUMBER depending on the direction. If the direction is towards the IMS Core, cut CC+HEADER_NUMBER. If the direction is towards the outside world then add CC+HEADER_NUMBER. +; ${EXTEN:n} is used to achieve this slicing of numbers, where "n" is the digit that needs to stay along with the digits that come after it. +; In the below case it's the number after 0 and including 0, so 0912584710 will be recognized inside my private network. This needs to be adjusted depending on your needs like the length of your head number and your MSISDN. +; After doing that we need to send the call to the ICSCF as we don't know where the user is registered, the rest will be done inside the IMS Core+Open5GS. +; +; It's preconfigured below on digit 13 (UK users please change it! not to trigger any bad luck!). + + +[incoming] + +; +49 228 1234567 + any +exten => _${ENUM_PREFIX_FOR_DE}${PHONE_NR_HEAD}X.,1,Verbose(incoming call from ICP from ${CALLERID(num)} calling to ${EXTEN:13}) +same => n,Verbose(check for exten ${EXTEN} 8 ${EXTEN:8} 9 ${EXTEN:9} 10 ${EXTEN:10} 11 ${EXTEN:11} 13 ${EXTEN:13} ) +; Cutting until digit 13 CUT 0912584710 +; Set some headers and send to icscf to reach the users. +same => n,Dial(PJSIP/${ICP_IN}/sip:${EXTEN:13}@${IMS_CN_DOMAIN},120,b(outgoing^ims_inc^1)) +same => n,Hangup() + +[outgoing] + +; Devices can usually perform calls in two ways i.e. either the call will start with 0 (in the IMS is not possible) or with + before the dialing number. + +; Below is for the scenario where there is 0 before the dialing number. This is not applicable since IMS is 3GPP compatible and the dialed number follows E164 standards. +exten => _0X.,1,Verbose(outgoing context leading null ${EXTEN} calling from IMS User ${CALLERID(num)} ) +same => n,Dial(PJSIP/${ICP_OUT}/sip:${ENUM_PREFIX_FOR_DE}${EXTEN:1}@${SIPTRUNK_DOMAIN},120,b(outgoing^headers^1)) +same => n,Hangup() + +; Below is for the scenario where there is + before the dialing number.And, this is the one being used since we use E164 in IMS. +exten => _${ENUM_PREFIX_FOR_DE}X.,1,Verbose(outgoing Call leading +49 calling from IMS User ${CALLERID(num)} to ${EXTEN} ) +same => n,Verbose(Sending INVITE to ICP) +; we set the head number and add the MSISDN to it then set it in the "From" header +same => n,Set(CALLERID(num)=${ENUM_PREFIX_FOR_DE}${PHONE_NR_HEAD}${CALLERID(num)}) +; Setting some headers and sends the INVITE to the Provider/ICP +same => n,Dial(PJSIP/${ICP_OUT}/sip:${EXTEN}@${SIPTRUNK_DOMAIN},120,b(outgoing^ims_out^1)) +same => n,Hangup() + +; Below headers are sed in outgoing. +exten => ims_out,1,Verbose(Setting required headers in outgoing INVITE) +; Set the P-Preferred-Identity and optionally P-Preferred-Identity (PAI is only a Network thing). +; Adding the MSISDN to the head number before sending it out. +same => n,Set(PJSIP_HEADER(add,${PPI_HEADER})=) +same => n,Set(PJSIP_HEADER(add,${PAI_HEADER})=) +; Set the P-Early-Media to supported. +; Asterisk knows nothing about RFC5009, but it's required by 3GPP so we add it as hack. +same => n,Set(PJSIP_HEADER(add,${P_HEADER})=Supported) +same => n,Set(PJSIP_HEADER(add,Supported)=199) +same => n,Return() + +; For incoming we need to set the PAI since some devices need this header. +exten => ims_inc,1,Verbose(Setting required headers in incoming INVITE) +same => n,Set(PJSIP_HEADER(add,${PAI_HEADER})=) +same => n,Set(PJSIP_HEADER(add,${PAI_HEADER})=) +same => n,Set(PJSIP_HEADER(add,${P_HEADER})=Supported) +same => n,Set(PJSIP_HEADER(add,Supported)=199) +same => n,Return() + +[IMS_INC] + +include => outgoing + +; Voicemail IMS is a WIP. +; Need to add appropriate IFC for it, don't forget to configure your MSISDN in the voicemail.conf. + +; Configure the start of your number instead of "09125" e.g. if your MSISDN starts with 09125123456 then exten => _09125X. +exten => _09125X.,1,Verbose(1, Caller ${CALLERID(all)} has entered Voicemail for ${EXTEN} from IMS ) +same => n,VoiceMail(${EXTEN}) + +exten => 500,1,Ringing() +exten => 500,n,Wait(2) +exten => 500,n,Answer +exten => 500,n,Wait(2) +exten => 500,n,VoiceMailMain(${CALLERID(num)}) +exten => 500,n,HangUp() +exten => 500,n,PlayBack(vm-goodbye) +exten => 500,n,HangUp() diff --git a/ibcf/config/indications.conf b/ibcf/config/indications.conf new file mode 100644 index 0000000..6953c3e --- /dev/null +++ b/ibcf/config/indications.conf @@ -0,0 +1,21 @@ +[general] +country = de + +[de] +description = Germany +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +ringcadence = 1000,4000 +dial = 425 +busy = 425/480,0/480 +ring = 425/1000,0/4000 +congestion = 425/240,0/240 +callwaiting = !425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,0 +; DIALRECALL - not specified +dialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 +; RECORDTONE - not specified +record = 1400/80,0/15000 +info = 950/330,1400/330,1800/330,0/1000 +stutter = 425+400 + +; Additional country configurations can be found in the Asterisk source +; at /configs/samples/indications.conf.sample diff --git a/ibcf/config/logger.conf b/ibcf/config/logger.conf new file mode 100644 index 0000000..8b0a1c1 --- /dev/null +++ b/ibcf/config/logger.conf @@ -0,0 +1,9 @@ +[general] + +[logfiles] + +console = verbose,notice,warning,error + +;messages = notice,warning,error +;full = verbose,notice,warning,error,debug +;security = security diff --git a/ibcf/config/modules.conf b/ibcf/config/modules.conf new file mode 100644 index 0000000..b2277e2 --- /dev/null +++ b/ibcf/config/modules.conf @@ -0,0 +1,130 @@ +[modules] +autoload = no + +; This is a minimal module load. We are loading only the modules +; required for the Asterisk features used in the "Super Awesome +; Company" configuration. + +; Applications + +load = app_bridgewait.so +load = app_dial.so +load = app_playback.so +load = app_stack.so +load = app_verbose.so +load = app_voicemail.so +load = app_directory.so +load = app_confbridge.so +load = app_queue.so +load = app_echo.so +load = app_mp3.so +load = app_transfer.so + + +; Bridging + +load = bridge_builtin_features.so +load = bridge_builtin_interval_features.so +load = bridge_holding.so +load = bridge_native_rtp.so +load = bridge_simple.so +load = bridge_softmix.so + +; Call Detail Records + +load = cdr_custom.so + +; Channel Drivers + +load = chan_bridge_media.so +load = chan_pjsip.so + +; Codecs + +load = codec_gsm.so +load = codec_resample.so +load = codec_ulaw.so +load = codec_g722.so +load = codec_evs.so +load = codec_alaw.so +load = codec_amr.so + +; Formats + +load = format_gsm.so +load = format_pcm.so +load = format_wav_gsm.so +load = format_wav.so +load = format_mp3.so + +; Functions + +load = func_callerid.so +load = func_cdr.so +load = func_pjsip_endpoint.so +load = func_sorcery.so +load = func_devstate.so +load = func_strings.so +load = func_srv.so + +; Core/PBX + +load = pbx_config.so + +; Resources + +load = res_http_websocket.so +load = res_musiconhold.so +load = res_pjproject.so +load = res_pjsip_acl.so +load = res_pjsip_authenticator_digest.so +load = res_pjsip_caller_id.so +load = res_pjsip_dialog_info_body_generator.so +load = res_pjsip_diversion.so +load = res_pjsip_dtmf_info.so +load = res_pjsip_endpoint_identifier_anonymous.so +load = res_pjsip_endpoint_identifier_ip.so +load = res_pjsip_endpoint_identifier_user.so +load = res_pjsip_exten_state.so +load = res_pjsip_header_funcs.so +load = res_pjsip_logger.so +load = res_pjsip_messaging.so +load = res_pjsip_mwi_body_generator.so +load = res_pjsip_mwi.so +load = res_pjsip_nat.so +load = res_pjsip_notify.so +load = res_pjsip_one_touch_record_info.so +load = res_pjsip_outbound_authenticator_digest.so +load = res_pjsip_outbound_publish.so +load = res_pjsip_outbound_registration.so +load = res_pjsip_path.so +load = res_pjsip_pidf_body_generator.so +load = res_pjsip_pidf_digium_body_supplement.so +load = res_pjsip_pidf_eyebeam_body_supplement.so +load = res_pjsip_publish_asterisk.so +load = res_pjsip_pubsub.so +load = res_pjsip_refer.so +load = res_pjsip_registrar.so +load = res_pjsip_rfc3326.so +load = res_pjsip_sdp_rtp.so +load = res_pjsip_send_to_voicemail.so +load = res_pjsip_session.so +load = res_pjsip.so +load = res_pjsip_t38.so +load = res_pjsip_transport_websocket.so +load = res_pjsip_xpidf_body_generator.so +load = res_rtp_asterisk.so +load = res_sorcery_astdb.so +load = res_sorcery_config.so +load = res_sorcery_memory.so +load = res_sorcery_realtime.so +load = res_timing_timerfd.so +load = res_format_attr_amr.so +load = res_format_attr_evs.so + +; Do not load res_hep and kin unless you are using HEP monitoring +; in your network. + +noload = res_hep.so +noload = res_hep_pjsip.so +noload = res_hep_rtcp.so diff --git a/ibcf/config/musiconhold.conf b/ibcf/config/musiconhold.conf new file mode 100644 index 0000000..bc3ba21 --- /dev/null +++ b/ibcf/config/musiconhold.conf @@ -0,0 +1,5 @@ +[general] + +[default] +mode = files +directory = moh diff --git a/ibcf/config/pjsip.conf b/ibcf/config/pjsip.conf new file mode 100644 index 0000000..fbd5b84 --- /dev/null +++ b/ibcf/config/pjsip.conf @@ -0,0 +1,144 @@ +; Configure here your ICP Link towards outside (SIP Trunk account, etc.) + +[global] +type=global +user_agent=IBCF VoLTE +keep_alive_interval=20 +; Add some default Number to be used in case From not specified otherwise you can comment it out +default_from_user=_DEFAULT_NUMBER +;endpoint_identifier_order=ip +ignore_uri_user_options=yes +max_forwards=70 +allow_sending_180_after_183=yes + +; Protect your IBCF with ACL. Configure permit/deny IPs in acl.conf. This is important to prevent untrusted IP from trying to reach this PBX. +[ibcf_acl] +type=acl +acl=ibcf_acl + +; Transport definitions, nothing important here, unless you want to change something +[transport-tcp-nat] +type=transport +protocol=tcp +bind=0.0.0.0:5090 +tos=192 +local_net=172.22.0.0/24 + +[transport-udp] +type=transport +protocol=udp +bind=0.0.0.0:5090 +local_net=172.22.0.0/24 +;tos=192 + +; Below configures the registration info for your Trunking Account. If you use a real ICP over the "Ic" Reference Point the configuration is different, it will be more like static registration. +; Change the values of PROVIDER_PCSCF, PROVIDER_SIP_DOMAIN with your provider's info. + +[defaults_registration](!) +type=registration +transport=transport-tcp-nat +outbound_proxy=sip:PROVIDER_PCSCF\;transport=tcp\;lr +server_uri=sip:PROVIDER_SIP_DOMAIN\;transport=tcp\;lr +retry_interval=900 +forbidden_retry_interval=1800 +fatal_retry_interval=1800 +expiration=480 +auth_rejection_permanent=no +line=yes +max_retries=99 + +; Replace with your account data!! +; Replace the values of AUTH_USERNAME@PROVIDER_DOMAIN and CONTACT_USER with your provider's info. +[ICP_LINK](defaults_registration) +outbound_auth=ICP_LINK +client_uri=sip:AUTH_USERNAME@PROVIDER_DOMAIN +contact_user=CONTACT_USER +endpoint=ICP_LINK_in + +; Below configures the type of authentication. In register mode you need to provide a user name and password. +; Change the values of PROVIDER_USERNAME, PROVIDER_PASSWD and PROVIDER_DOMAIN with your provider's info. +[ICP_LINK] +type=auth +auth_type=userpass +username=PROVIDER_USERNAME +password=PROVIDER_PASSWD +realm=PROVIDER_DOMAIN + +; Change the values of PROVIDER_PCSCF with your provider's info. +[defaults_endpoint](!) +type=endpoint +transport=transport-tcp-nat +;removed for double contacts +outbound_proxy=sip:PROVIDER_PCSCF\;transport=tcp\;lr +allow=!all,amrwb,amr,g722,alaw,h264 +inband_progress=yes +direct_media=no +dtmf_mode=auto +;send_pai=yes +;send_rpid=yes +;100rel=required +100rel=yes +tos_audio=184 +rtp_symmetric=yes +rtp_keepalive=1 +moh_suggest=default +moh_passthrough=yes +send_diversion=yes +suppress_q850_reason_headers=yes +user_eq_phone=yes +preferred_codec_only=yes +;tos_video=af41 +;cos_video=4 +direct_media_glare_mitigation=outgoing +suppress_moh_on_sendonly=yes +use_ptime=yes + +; Outgoing Leg +; Change the values of PROVIDER_DOMAIN and CONTACT_USER with your provider's info. +[ICP_LINK_out](defaults_endpoint) +context=outgoing +outbound_auth=ICP_LINK +aors=ICP_LINK +;media_encryption=no +from_domain=PROVIDER_DOMAIN +contact_user=CONTACT_USER + +[ICP_LINK_in](defaults_endpoint) +outbound_auth=ICP_LINK +context=incoming + +; Change the value of CONTACT_USER with your provider's info. +[ICP_LINK] +type=aor +contact=sip:CONTACT_USER + +; Match the incoming request to only a specific IPs like your provider's subnet and your IMS Core internal subnet. +[ICP_LINK_in] +type=identify +endpoint=ICP_LINK_in +match=PROVIDER_SUBNET/24 +match=DOCKER_HOST_SUBNET/24 + +[ims_core] +type=endpoint +aors=ims_core +allow_unauthenticated_options=yes +transport=transport-udp +context=IMS_INC +allow=!all,evs,amrwb,amr,g722,alaw,h264 +dtmf_mode=auto +tos_audio=184 +send_diversion=yes +preferred_codec_only=yes + + +[ims_core] +type=identify +endpoint=ims_core +match=172.22.0.0/24 + +[ims_core] +type=aor +;contact=sip:172.22.0.20 +max_contacts=3 +;qualify_frequency=60 diff --git a/ibcf/config/pjsip_notify.conf b/ibcf/config/pjsip_notify.conf new file mode 100644 index 0000000..8224ee1 --- /dev/null +++ b/ibcf/config/pjsip_notify.conf @@ -0,0 +1,57 @@ +; rfc3842 +; put empty "Content=>" at the end to have CRLF after last body line + +[clear-mwi] +Event=>message-summary +Content-type=>application/simple-message-summary +Content=>Messages-Waiting: no +Content=>Message-Account: sip:asterisk@127.0.0.1 +Content=>Voice-Message: 0/0 (0/0) +Content=> + +; Aastra + +[aastra-check-cfg] +Event=>check-sync + +[aastra-xml] +Event=>aastra-xml + +; Digium + +[digium-check-cfg] +Event=>check-sync + +; Linksys + +[linksys-cold-restart] +Event=>reboot_now + +[linksys-warm-restart] +Event=>restart_now + +; Polycom + +[polycom-check-cfg] +Event=>check-sync + +; Sipura + +[sipura-check-cfg] +Event=>resync + +[sipura-get-report] +Event=>report + +; snom + +[snom-check-cfg] +Event=>check-sync\;reboot=false + +[snom-reboot] +Event=>check-sync\;reboot=true + +; Cisco + +[cisco-check-cfg] +Event=>check-sync diff --git a/ibcf/config/queues.conf b/ibcf/config/queues.conf new file mode 100644 index 0000000..8aaa0b4 --- /dev/null +++ b/ibcf/config/queues.conf @@ -0,0 +1,19 @@ +[general] +monitor-type = MixMonitor + +;========================Sales Queue == +; Calls all sales persons in a ring-all fashion +[sales] +strategy=ringall +member => PJSIP/1109 ; Terry Jules - Director of Sales +member => PJSIP/1105 ; Garnet Claude - Sales Associate +member => PJSIP/1112 ; Franny Ocean - Sales Associate + +;===================== Customer Advocate Queue == +; Calls all customer advocates in a ring-all fashion +[customer_advocate] +strategy=ringall +member => PJSIP/1101 ; Maria Berny - Director of Customer Experience +member => PJSIP/1115 ; Dusty Williams - Customer Advocate +member => PJSIP/1102 ; Tommy Briar - Customer Advocate + diff --git a/ibcf/config/rtp.conf b/ibcf/config/rtp.conf new file mode 100644 index 0000000..37283df --- /dev/null +++ b/ibcf/config/rtp.conf @@ -0,0 +1,3 @@ +[general] +rtpstart=10000 +rtpend=10100 \ No newline at end of file diff --git a/ibcf/config/voicemail.conf b/ibcf/config/voicemail.conf new file mode 100644 index 0000000..75bb8a7 --- /dev/null +++ b/ibcf/config/voicemail.conf @@ -0,0 +1,17 @@ +[general] +format=wav49 ; Voicemail file format +maxmsg=100 ; Maximum number of messages per mailbox +minsecs=3 ; Minimum length of a message in seconds +maxsecs=300 ; Maximum length of a message in seconds +maxlogins=3 ; Maximum number of incorrect password attempts before hanging up +sendvoicemail=yes ; Allow sending voicemail (yes/no) +emailsubject=New Voicemail Message ${VM_MSGNUM} in Mailbox ${VM_MAILBOX} +fromstring=Voicemail +serveremail=my_vonr-vm@voicemail.IMS_DOMAIN ; Default sender email address + + +[IMS_Users] +; Voicemail context for all internal users in the example.com domain. +; Format is : MSISDN => VM_PIN,Name,Email +MSISDN => 1234,VoNR_One,MSISDN@voicemail.IMS_DOMAIN +MSISDN => 4567,VoNR_Two,MSISDN@voicemail.IMS_DOMAIN diff --git a/ibcf/menuselect.makedeps b/ibcf/menuselect.makedeps new file mode 100644 index 0000000..89d2c79 --- /dev/null +++ b/ibcf/menuselect.makedeps @@ -0,0 +1,234 @@ +MENUSELECT_DEPENDS_chan_mobile=BLUETOOTH +MENUSELECT_DEPENDS_res_config_mysql=MYSQLCLIENT +MENUSELECT_DEPENDS_app_flash=DAHDI +MENUSELECT_DEPENDS_app_voicemail_imap=IMAP_TK +MENUSELECT_DEPENDS_app_voicemail_odbc=GENERIC_ODBC +MENUSELECT_DEPENDS_app_jack=JACK RESAMPLE +MENUSELECT_DEPENDS_app_meetme=DAHDI +MENUSELECT_DEPENDS_binaural_rendering_in_bridge_softmix=FFTW3 +MENUSELECT_DEPENDS_cdr_adaptive_odbc=GENERIC_ODBC +MENUSELECT_DEPENDS_cdr_beanstalkd=BEANSTALK +MENUSELECT_DEPENDS_cdr_odbc=GENERIC_ODBC +MENUSELECT_DEPENDS_cdr_pgsql=PGSQL +MENUSELECT_DEPENDS_cdr_radius=RADIUS +MENUSELECT_DEPENDS_cdr_sqlite3_custom=SQLITE3 +MENUSELECT_DEPENDS_cdr_tds=FREETDS +MENUSELECT_DEPENDS_cel_odbc=GENERIC_ODBC +MENUSELECT_DEPENDS_cel_beanstalkd=BEANSTALK +MENUSELECT_DEPENDS_cel_pgsql=PGSQL +MENUSELECT_DEPENDS_cel_radius=RADIUS +MENUSELECT_DEPENDS_cel_sqlite3_custom=SQLITE3 +MENUSELECT_DEPENDS_cel_tds=FREETDS +MENUSELECT_DEPENDS_chan_dahdi=DAHDI TONEZONE PRI SS7 OPENR2 +MENUSELECT_DEPENDS_chan_iax2=CRYPTO +MENUSELECT_DEPENDS_chan_motif=IKSEMEL OPENSSL +MENUSELECT_DEPENDS_chan_pjsip=PJPROJECT +MENUSELECT_DEPENDS_chan_console=PORTAUDIO +MENUSELECT_DEPENDS_codec_codec2=CODEC2 +MENUSELECT_DEPENDS_codec_dahdi=DAHDI +MENUSELECT_DEPENDS_codec_gsm=GSM +MENUSELECT_DEPENDS_codec_ilbc=ILBC +MENUSELECT_DEPENDS_codec_speex=SPEEX SPEEX_PREPROCESS SPEEXDSP +MENUSELECT_DEPENDS_codec_amr=AMR_NB AMR_WB_DECODER AMR_WB_ENCODER +MENUSELECT_DEPENDS_codec_evs=EVS +MENUSELECT_DEPENDS_codec_opus=XMLSTARLET BASH +MENUSELECT_DEPENDS_codec_silk=XMLSTARLET BASH +MENUSELECT_DEPENDS_codec_siren7=XMLSTARLET BASH +MENUSELECT_DEPENDS_codec_siren14=XMLSTARLET BASH +MENUSELECT_DEPENDS_codec_g729a=XMLSTARLET BASH +MENUSELECT_DEPENDS_format_ogg_vorbis=VORBIS OGG +MENUSELECT_DEPENDS_format_ogg_speex=SPEEX OGG +MENUSELECT_DEPENDS_func_aes=CRYPTO +MENUSELECT_DEPENDS_func_curl=CURL +MENUSELECT_DEPENDS_func_iconv=ICONV +MENUSELECT_DEPENDS_func_odbc=GENERIC_ODBC +MENUSELECT_DEPENDS_func_pjsip_aor=PJPROJECT +MENUSELECT_DEPENDS_func_pjsip_contact=PJPROJECT +MENUSELECT_DEPENDS_func_pjsip_endpoint=PJPROJECT +MENUSELECT_DEPENDS_func_speex=SPEEX SPEEX_PREPROCESS SPEEXDSP +MENUSELECT_DEPENDS_pbx_dundi=ZLIB CRYPTO +MENUSELECT_DEPENDS_pbx_lua=LUA +MENUSELECT_DEPENDS_res_config_curl=CURL +MENUSELECT_DEPENDS_res_config_odbc=GENERIC_ODBC +MENUSELECT_DEPENDS_res_config_sqlite3=SQLITE3 +MENUSELECT_DEPENDS_res_crypto=OPENSSL +MENUSELECT_DEPENDS_res_curl=CURL +MENUSELECT_DEPENDS_res_geolocation=LIBXML2 LIBXSLT +MENUSELECT_DEPENDS_res_http_media_cache=CURL +MENUSELECT_DEPENDS_res_http_post=GMIME +MENUSELECT_DEPENDS_res_odbc=GENERIC_ODBC +MENUSELECT_DEPENDS_res_odbc_transaction=GENERIC_ODBC +MENUSELECT_DEPENDS_res_pjproject=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_acl=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_authenticator_digest=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_caller_id=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_config_wizard=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_dialog_info_body_generator=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_diversion=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_dlg_options=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_dtmf_info=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_empty_info=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_endpoint_identifier_anonymous=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_endpoint_identifier_ip=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_endpoint_identifier_user=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_exten_state=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_geolocation=PJPROJECT LIBXML2 +MENUSELECT_DEPENDS_res_pjsip_header_funcs=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_logger=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_messaging=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_mwi=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_mwi_body_generator=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_nat=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_notify=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_one_touch_record_info=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_outbound_authenticator_digest=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_outbound_publish=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_outbound_registration=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_path=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_pidf_body_generator=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_pidf_digium_body_supplement=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_pidf_eyebeam_body_supplement=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_publish_asterisk=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_pubsub=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_refer=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_registrar=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_rfc3326=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_rfc3329=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_sdp_rtp=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_send_to_voicemail=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_session=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_sips_contact=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_stir_shaken=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_t38=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_transport_websocket=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_xpidf_body_generator=PJPROJECT +MENUSELECT_DEPENDS_res_resolver_unbound=UNBOUND +MENUSELECT_DEPENDS_res_rtp_asterisk=OPENSSL PJPROJECT +MENUSELECT_DEPENDS_res_srtp=SRTP OPENSSL +MENUSELECT_DEPENDS_res_stasis_test=TEST_FRAMEWORK +MENUSELECT_DEPENDS_res_stir_shaken=CURL LIBJWT +MENUSELECT_DEPENDS_res_timing_dahdi=DAHDI +MENUSELECT_DEPENDS_res_timing_timerfd=TIMERFD +MENUSELECT_DEPENDS_res_xmpp=IKSEMEL OPENSSL +MENUSELECT_DEPENDS_res_calendar_caldav=NEON ICAL LIBXML2 +MENUSELECT_DEPENDS_res_calendar_ews=NEON29 +MENUSELECT_DEPENDS_res_calendar_exchange=NEON ICAL IKSEMEL +MENUSELECT_DEPENDS_res_calendar_icalendar=NEON ICAL +MENUSELECT_DEPENDS_res_config_ldap=LDAP +MENUSELECT_DEPENDS_res_config_pgsql=PGSQL +MENUSELECT_DEPENDS_res_corosync=COROSYNC +MENUSELECT_DEPENDS_res_fax_spandsp=SPANDSP +MENUSELECT_DEPENDS_res_hep_pjsip=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_aoc=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_history=PJPROJECT +MENUSELECT_DEPENDS_res_pjsip_phoneprov_provider=PJPROJECT +MENUSELECT_DEPENDS_res_prometheus=PJPROJECT +MENUSELECT_DEPENDS_res_snmp=NETSNMP +MENUSELECT_DEPENDS_res_timing_kqueue=KQUEUE +MENUSELECT_DEPENDS_res_digium_phone=XMLSTARLET BASH +MENUSELECT_DEPENDS_res_pjsip_config_sangoma=XMLSTARLET BASH +MENUSELECT_DEPENDS_test_abstract_jb=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_acl=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_aeap=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_aeap_speech=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_aeap_transaction=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_aeap_transport=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_amihooks=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_aoc=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_app=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_ari=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_ari_model=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_ast_format_str_reduce=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_astobj2=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_astobj2_thrash=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_astobj2_weaken=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_bridging=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_bucket=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_callerid=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_capture=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_cdr=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_cel=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_channel=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_channel_feature_hooks=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_config=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_conversions=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_core_codec=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_core_format=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_crypto=TEST_FRAMEWORK CRYPTO +MENUSELECT_DEPENDS_test_data_buffer=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_db=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_devicestate=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_dlinklists=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_dns=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_dns_naptr=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_dns_query_set=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_dns_recurring=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_dns_srv=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_endpoints=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_event=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_expr=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_file=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_format_cache=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_format_cap=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_func_file=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_gosub=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_hashtab_thrash=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_heap=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_http_media_cache=TEST_FRAMEWORK CURL +MENUSELECT_DEPENDS_test_jitterbuf=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_json=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_linkedlists=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_locale=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_logger=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_media_cache=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_message=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_mwi=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_named_lock=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_netsock2=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_optional_api=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_pbx=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_poll=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_res_pjsip_scheduler=TEST_FRAMEWORK PJPROJECT +MENUSELECT_DEPENDS_test_res_pjsip_session_caps=TEST_FRAMEWORK PJPROJECT +MENUSELECT_DEPENDS_test_res_rtp=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_res_stasis=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_sched=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_scope_trace=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_scoped_lock=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_security_events=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_skel=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_sorcery=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_sorcery_astdb=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_sorcery_memory_cache_thrash=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_sorcery_realtime=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_stasis=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_stasis_channels=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_stasis_endpoints=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_stasis_state=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_stream=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_stringfields=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_strings=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_substitution=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_taskprocessor=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_threadpool=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_time=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_uri=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_utils=TEST_FRAMEWORK CRYPTO +MENUSELECT_DEPENDS_test_uuid=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_vector=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_voicemail_api=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_websocket_client=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_xml_escape=TEST_FRAMEWORK +MENUSELECT_DEPENDS_test_res_prometheus=TEST_FRAMEWORK CURL +MENUSELECT_DEPENDS_BETTER_BACKTRACES=BFD DLADDR +MENUSELECT_DEPENDS_BUILD_NATIVE=NATIVE_ARCH +MENUSELECT_DEPENDS_REBUILD_PARSERS=BISON FLEX +MENUSELECT_DEPENDS_USE_HOARD_ALLOCATOR=HOARD +MENUSELECT_DEPENDS_ADDRESS_SANITIZER=HAVE_ADDRESS_SANITIZER +MENUSELECT_DEPENDS_THREAD_SANITIZER=HAVE_THREAD_SANITIZER +MENUSELECT_DEPENDS_LEAK_SANITIZER=HAVE_LEAK_SANITIZER +MENUSELECT_DEPENDS_UNDEFINED_SANITIZER=HAVE_UNDEFINED_SANITIZER +MENUSELECT_DEPENDS_smsq=POPT +MENUSELECT_DEPENDS_conf_bridge_binaural_hrir_importer=SNDFILE +MENUSELECT_DEPENDS_astman=NEWT diff --git a/ibcf/menuselect.makeopts b/ibcf/menuselect.makeopts new file mode 100644 index 0000000..c777e1e --- /dev/null +++ b/ibcf/menuselect.makeopts @@ -0,0 +1,122 @@ +MENUSELECT_ADDONS=chan_mobile chan_ooh323 res_config_mysql +MENUSELECT_APPS=app_flash app_skel app_voicemail_imap app_voicemail_odbc app_statsd app_meetme +MENUSELECT_BRIDGES=binaural_rendering_in_bridge_softmix +MENUSELECT_CDR=cdr_beanstalkd +MENUSELECT_CEL=cel_beanstalkd +MENUSELECT_CHANNELS=chan_dahdi +MENUSELECT_CODECS=codec_dahdi codec_opus codec_silk codec_siren7 codec_siren14 codec_g729a +MENUSELECT_FORMATS= +MENUSELECT_FUNCS= +MENUSELECT_PBX= +MENUSELECT_RES=res_ari_mailboxes res_mwi_external res_mwi_external_ami res_pjsip_stir_shaken res_stasis_mailbox res_stasis_test res_stir_shaken res_timing_dahdi res_chan_stats res_cliexec res_corosync res_endpoint_stats res_remb_modifier res_timing_kqueue res_digium_phone res_pjsip_config_sangoma +MENUSELECT_TESTS=test_abstract_jb test_acl test_aeap test_aeap_speech test_aeap_transaction test_aeap_transport test_amihooks test_aoc test_app test_ari test_ari_model test_ast_format_str_reduce test_astobj2 test_astobj2_thrash test_astobj2_weaken test_bridging test_bucket test_callerid test_capture test_cdr test_cel test_channel test_channel_feature_hooks test_config test_conversions test_core_codec test_core_format test_crypto test_data_buffer test_db test_devicestate test_dlinklists test_dns test_dns_naptr test_dns_query_set test_dns_recurring test_dns_srv test_endpoints test_event test_expr test_file test_format_cache test_format_cap test_func_file test_gosub test_hashtab_thrash test_heap test_http_media_cache test_jitterbuf test_json test_linkedlists test_locale test_logger test_media_cache test_message test_mwi test_named_lock test_netsock2 test_optional_api test_pbx test_poll test_res_pjsip_scheduler test_res_pjsip_session_caps test_res_rtp test_res_stasis test_sched test_scope_trace test_scoped_lock test_security_events test_skel test_sorcery test_sorcery_astdb test_sorcery_memory_cache_thrash test_sorcery_realtime test_stasis test_stasis_channels test_stasis_endpoints test_stasis_state test_stream test_stringfields test_strings test_substitution test_taskprocessor test_threadpool test_time test_uri test_utils test_uuid test_vector test_voicemail_api test_websocket_client test_xml_escape test_res_prometheus +MENUSELECT_CFLAGS=BUILD_NATIVE OPTIONAL_API +MENUSELECT_UTILS=astcanary astdb2sqlite3 astdb2bdb +MENUSELECT_AGIS= +MENUSELECT_CORE_SOUNDS=CORE-SOUNDS-EN-WAV CORE-SOUNDS-EN-ALAW CORE-SOUNDS-EN-GSM CORE-SOUNDS-EN-G722 +MENUSELECT_MOH=MOH-OPSOUND-WAV MOH-OPSOUND-ALAW MOH-OPSOUND-GSM MOH-OPSOUND-G722 +MENUSELECT_EXTRA_SOUNDS=EXTRA-SOUNDS-EN-WAV EXTRA-SOUNDS-EN-ALAW EXTRA-SOUNDS-EN-GSM EXTRA-SOUNDS-EN-G722 +MENUSELECT_BUILD_DEPS=bridge_holding app_cdr func_periodic_hook app_confbridge res_speech res_agi res_stasis res_adsi res_smdi res_audiosocket res_odbc res_crypto res_xmpp res_pjsip res_pjsip_pubsub res_pjsip_session res_rtp_multicast res_curl app_chanspy func_cut func_groupcount func_uri res_ael_share res_http_websocket res_ari res_ari_model res_stasis_recording res_stasis_playback res_stasis_answer res_stasis_snoop res_stasis_device_state func_curl res_odbc_transaction res_sorcery_config res_pjproject res_sorcery_memory res_sorcery_astdb res_statsd res_geolocation res_pjsip_outbound_publish chan_pjsip res_calendar res_fax res_hep res_phoneprov res_pjsip_outbound_registration DONT_OPTIMIZE G711_NEW_ALGORITHM +MENUSELECT_DEPSFAILED=MENUSELECT_APPS=app_flash +MENUSELECT_DEPSFAILED=MENUSELECT_CDR=cdr_beanstalkd +MENUSELECT_DEPSFAILED=MENUSELECT_CEL=cel_beanstalkd +MENUSELECT_DEPSFAILED=MENUSELECT_CHANNELS=chan_dahdi +MENUSELECT_DEPSFAILED=MENUSELECT_CODECS=codec_dahdi +MENUSELECT_DEPSFAILED=MENUSELECT_RES=res_pjsip_stir_shaken +MENUSELECT_DEPSFAILED=MENUSELECT_RES=res_stasis_test +MENUSELECT_DEPSFAILED=MENUSELECT_RES=res_stir_shaken +MENUSELECT_DEPSFAILED=MENUSELECT_RES=res_timing_dahdi +MENUSELECT_DEPSFAILED=MENUSELECT_RES=res_timing_kqueue +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_abstract_jb +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_acl +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_aeap +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_aeap_speech +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_aeap_transaction +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_aeap_transport +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_amihooks +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_aoc +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_app +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_ari +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_ari_model +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_ast_format_str_reduce +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_astobj2 +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_astobj2_thrash +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_astobj2_weaken +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_bridging +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_bucket +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_callerid +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_capture +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_cdr +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_cel +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_channel +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_channel_feature_hooks +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_config +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_conversions +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_core_codec +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_core_format +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_crypto +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_data_buffer +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_db +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_devicestate +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_dlinklists +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_dns +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_dns_naptr +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_dns_query_set +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_dns_recurring +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_dns_srv +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_endpoints +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_event +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_expr +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_file +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_format_cache +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_format_cap +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_func_file +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_gosub +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_hashtab_thrash +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_heap +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_http_media_cache +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_jitterbuf +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_json +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_linkedlists +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_locale +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_logger +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_media_cache +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_message +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_mwi +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_named_lock +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_netsock2 +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_optional_api +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_pbx +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_poll +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_res_pjsip_scheduler +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_res_pjsip_session_caps +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_res_rtp +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_res_stasis +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_sched +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_scope_trace +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_scoped_lock +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_security_events +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_skel +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_sorcery +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_sorcery_astdb +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_sorcery_memory_cache_thrash +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_sorcery_realtime +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_stasis +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_stasis_channels +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_stasis_endpoints +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_stasis_state +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_stream +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_stringfields +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_strings +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_substitution +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_taskprocessor +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_threadpool +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_time +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_uri +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_utils +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_uuid +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_vector +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_voicemail_api +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_websocket_client +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_xml_escape +MENUSELECT_DEPSFAILED=MENUSELECT_TESTS=test_res_prometheus diff --git a/ibcf/start-asterisk.sh b/ibcf/start-asterisk.sh new file mode 100755 index 0000000..32d3107 --- /dev/null +++ b/ibcf/start-asterisk.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +cp /mnt/ibcf/config/* /etc/asterisk/ + +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/asterisk/pjsip.conf +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/asterisk/extensions.conf +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/asterisk/voicemail.conf + +# Add static route to route traffic back to UE as there is not NATing +ip r add ${UE_IPV4_IMS} via ${UPF_IP} + +# Start server. +echo 'Starting Asterisk' + +asterisk -f diff --git a/icscf/icscf.cfg b/icscf/icscf.cfg new file mode 100644 index 0000000..57312d1 --- /dev/null +++ b/icscf/icscf.cfg @@ -0,0 +1,56 @@ +# SIP / UDP +listen=udp:ICSCF_IP:4060 +# SIP / TCP +listen=tcp:ICSCF_IP:4060 +# SIP / TCP/TLS +#listen=tls:ICSCF_IP:4061 + +alias=IMS_DOMAIN + +#!define NETWORKNAME "IMS_DOMAIN" +#!define HOSTNAME "icscf.IMS_DOMAIN" + +#!subst "/NETWORKNAME/IMS_DOMAIN/" + +#!define ENUM_SUFFIX "e164.arpa." + +# Maximum lifetime of a subscription in seconds (same is advertised to UE) +#!substdef "/UE_SUBSCRIPTION_EXPIRES/SUBSCRIPTION_EXPIRES_ENV/g" + +# SIP-Address of capturing node, if not set, capturing is disabled. +##!define CAPTURE_NODE "sip:127.0.0.1:9060" + +# Connection URL for the database: +#!define DB_URL "mysql://icscf:heslo@MYSQL_IP/icscf" +##!define DB_URL2 "con2=>mysql://icscf:heslo@MYSQL_IP/icscf" + +# Allowed IPs for XML-RPC-Queries +##!define XMLRPC_WHITELIST_1 "127.0.0.1" +##!define XMLRPC_WHITELIST_2 "127.0.0.1" +##!define XMLRPC_WHITELIST_3 "127.0.0.1" + +# *** To run in debug mode: +# - define WITH_DEBUG +# +# *** To enable TLS support execute: +# - adjust CFGDIR/tls.cfg as needed +# - define WITH_TLS +# +# *** To enable XMLRPC support execute: +# - define WITH_XMLRPC +# - adjust route[XMLRPC] for access policy +# +# *** To enable a Homer SIP-Capter-Node: +# - define CAPTURE_NODE with a proper address +# +# *** To forwarding to PSTN for unknown users: +# - define PEERING +# +# Enabled Features for this host: +##!define WITH_DEBUG +##!define WITH_DEBUG_TRACE +#!define WITH_TCP +##!define WITH_TLS +#!define WITH_XMLRPC +##!define PEERING +##!define FALLBACK_AUTH diff --git a/icscf/icscf.xml b/icscf/icscf.xml new file mode 100644 index 0000000..4e63671 --- /dev/null +++ b/icscf/icscf.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + diff --git a/icscf/icscf_init.sh b/icscf/icscf_init.sh new file mode 100755 index 0000000..f8a5c73 --- /dev/null +++ b/icscf/icscf_init.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +mkdir -p /etc/kamailio_icscf +cp /mnt/icscf/icscf.cfg /etc/kamailio_icscf +cp /mnt/icscf/icscf.xml /etc/kamailio_icscf +cp /mnt/icscf/kamailio_icscf.cfg /etc/kamailio_icscf + +while ! mysqladmin ping -h ${MYSQL_IP} --silent; do + sleep 5; +done + +# Sleep until permissions are set +sleep 10; + +# Create ICSCF database, populate tables and grant privileges +if [[ -z "`mysql -u root -h ${MYSQL_IP} -qfsBe "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='icscf'" 2>&1`" ]]; +then + mysql -u root -h ${MYSQL_IP} -e "create database icscf;" + mysql -u root -h ${MYSQL_IP} icscf < /usr/local/src/kamailio/misc/examples/ims/icscf/icscf.sql + + ICSCF_USER_EXISTS=`mysql -u root -h ${MYSQL_IP} -s -N -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE User = 'icscf' AND Host = '%')"` + if [[ "$ICSCF_USER_EXISTS" == 0 ]] + then + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'icscf'@'%' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'provisioning'@'%' IDENTIFIED WITH mysql_native_password BY 'provi'"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'icscf'@'$ICSCF_IP' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'provisioning'@'$ICSCF_IP' IDENTIFIED WITH mysql_native_password BY 'provi'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON icscf.* TO 'icscf'@'%'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON icscf.* TO 'icscf'@'$ICSCF_IP'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON icscf.* TO 'provisioning'@'%'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON icscf.* TO 'provisioning'@'$ICSCF_IP'"; + mysql -u root -h ${MYSQL_IP} -e "FLUSH PRIVILEGES;" + fi +fi + +DOMAIN_PRESENT=`mysql -u root -h ${MYSQL_IP} icscf -s -N -e "SELECT count(*) FROM nds_trusted_domains WHERE trusted_domain='$IMS_DOMAIN';"` +if [[ "$DOMAIN_PRESENT" == 0 ]] +then + mysql -u root -h ${MYSQL_IP} icscf -e "INSERT INTO nds_trusted_domains (trusted_domain) VALUES ('$IMS_DOMAIN');" +fi + +URI_PRESENT=`mysql -u root -h ${MYSQL_IP} icscf -s -N -e "SELECT count(*) FROM s_cscf WHERE s_cscf_uri='sip:scscf.$IMS_DOMAIN:6060';"` +if [[ "$URI_PRESENT" == 0 ]] +then + mysql -u root -h ${MYSQL_IP} icscf -e "INSERT INTO s_cscf (name, s_cscf_uri) VALUES ('First and only S-CSCF', 'sip:scscf.$IMS_DOMAIN:6060');" +fi + +SCSCF_ID=`mysql -u root -h ${MYSQL_IP} icscf -s -N -e "SELECT id FROM s_cscf WHERE s_cscf_uri='sip:scscf.$IMS_DOMAIN:6060' LIMIT 1;"` +CAP_PRESENT=`mysql -u root -h ${MYSQL_IP} icscf -s -N -e "SELECT count(*) FROM s_cscf_capabilities WHERE id_s_cscf='$SCSCF_ID';"` +if [[ "$CAP_PRESENT" == 0 ]] +then + mysql -u root -h ${MYSQL_IP} icscf -e "INSERT INTO s_cscf_capabilities (id_s_cscf, capability) VALUES ('$SCSCF_ID', 0),('$SCSCF_ID', 1);" +fi + +SUBSCRIPTION_EXPIRES_ENV=3600 + +sed -i 's|ICSCF_IP|'$ICSCF_IP'|g' /etc/kamailio_icscf/icscf.cfg +sed -i 's|SUBSCRIPTION_EXPIRES_ENV|'$SUBSCRIPTION_EXPIRES_ENV'|g' /etc/kamailio_icscf/icscf.cfg +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/kamailio_icscf/icscf.cfg +sed -i 's|MYSQL_IP|'$MYSQL_IP'|g' /etc/kamailio_icscf/icscf.cfg + +sed -i 's|ICSCF_IP|'$ICSCF_IP'|g' /etc/kamailio_icscf/icscf.xml +sed -i 's|SUBSCRIPTION_EXPIRES_ENV|'$SUBSCRIPTION_EXPIRES_ENV'|g' /etc/kamailio_icscf/icscf.xml +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/kamailio_icscf/icscf.xml +sed -i 's|PYHSS_BIND_PORT|'$PYHSS_BIND_PORT'|g' /etc/kamailio_icscf/icscf.xml +sed -i 's|ICSCF_BIND_PORT|'$ICSCF_BIND_PORT'|g' /etc/kamailio_icscf/icscf.xml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/icscf/kamailio_icscf.cfg b/icscf/kamailio_icscf.cfg new file mode 100644 index 0000000..caed83b --- /dev/null +++ b/icscf/kamailio_icscf.cfg @@ -0,0 +1,643 @@ +#!KAMAILIO +# +# This config file implements the basic I-CSCF functionality +# - web: http://www.kamailio.org +# - git: http://sip-router.org +# +# Refer to the Core CookBook at http://www.kamailio.org/dokuwiki/doku.php +# for an explanation of possible statements, functions and parameters. +# +# Direct your questions about this file to: . +# +# For more information about the various parameters, functions and statements +# try http://sip-router.org/wiki/ . +# + +system.shutdownmode = 0 desc "System shutdown mode" +system.service = "Interrogating-CSCF" desc "Function of this server" + +include_file "icscf.cfg" + +####### Defined Values ######### +# *** Value defines - IDs used later in config + +# - flags +# FLT_ - per transaction (message) flags +# FLB_ - per branch flags + +#!define FLT_CAPTURE 1 + +#!ifdef WITH_XMLRPC +listen=tcp:127.0.0.1:4060 +#!endif + +####### Global Parameters ######### +debug=2 +log_stderror=no +sip_warning=no + +user_agent_header="User-Agent: Kamailio I-CSCF" +server_header="Server: Kamailio I-CSCF" +log_name="icscf" +log_prefix_mode=1 +log_prefix="{$mt $hdr(CSeq) $ci $cfg(route)} " + +/* comment the next line to enable the auto discovery of local aliases + based on reverse DNS on IPs (default on) */ +auto_aliases=no + +# Do SRV-Loadbalancing: +dns_srv_lb=on +# Always: Also try IPv6: +dns_try_ipv6=on +# Query NAPTR-Records as well: +dns_try_naptr=no + +#!ifdef WITH_XMLRPC +#!ifndef WITH_TCP +#!define WITH_TCP +#!endif +#!ifndef TCP_PROCESSES +# Number of TCP Processes +#!define TCP_PROCESSES 3 +#!endif +#!endif + +#!ifdef WITH_TCP +# life time of TCP connection when there is no traffic +# - a bit higher than registration expires to cope with UA behind NAT +tcp_connection_lifetime=UE_SUBSCRIPTION_EXPIRES +#!ifdef TCP_PROCESSES +tcp_children=TCP_PROCESSES +#!endif +#!else +disable_tcp=yes +#!endif + +check_via=no # (cmd. line: -v) +dns=no # (cmd. line: -r) +rev_dns=no # (cmd. line: -R) + +children=4 + +# ------------------ module loading ---------------------------------- +mpath="/usr/lib64/kamailio/modules_k/:/usr/lib64/kamailio/modules/:/usr/lib/kamailio/modules_k/:/usr/lib/kamailio/modules/:/usr/lib/x86_64-linux-gnu/kamailio/modules/:/usr/local/lib64/kamailio/modules" +# (we try both the lib64 and the lib directory) +loadmodule "tm.so" +loadmodule "sl.so" +loadmodule "rr.so" +loadmodule "pv.so" +loadmodule "textops.so" +loadmodule "maxfwd.so" +loadmodule "sanity.so" +loadmodule "siputils.so" +loadmodule "kex.so" +loadmodule "tmx.so" +loadmodule "pike.so" +loadmodule "corex.so" + +# Control interfaces: +loadmodule "ctl.so" +loadmodule "cfg_rpc.so" +#!ifdef WITH_XMLRPC +loadmodule "xmlrpc.so" +#!endif + +# Load the according DB-Module: +loadmodule "db_mysql.so" +#!ifdef DB_URL2 +loadmodule "db_cluster.so" +#!endif + +loadmodule "cdp.so" +loadmodule "cdp_avp.so" +loadmodule "xlog.so" + +loadmodule "ims_icscf.so" + +#!ifdef CAPTURE_NODE +loadmodule "siptrace.so" +#!endif + +#!ifdef WITH_DEBUG +loadmodule "debugger.so" +#!endif + +#!ifdef WITH_TLS +loadmodule "tls.so" +#!endif + +#!ifdef PEERING +loadmodule "enum.so" +loadmodule "dispatcher.so" +#!endif + +# ----------------- setting module-specific parameters --------------- +#!ifdef DB_URL2 +# ----- db_cluster params ----- +modparam("db_cluster", "connection", DB_URL) +modparam("db_cluster", "connection", DB_URL2) +modparam("db_cluster", "cluster", "cluster1=>con1=2s2s;con2=1s1s") +#!endif + +loadmodule "jsonrpcs.so" +# ----- jsonrpcs params ----- +modparam("jsonrpcs", "pretty_format", 1) +/* set the path to RPC fifo control file */ +modparam("jsonrpcs", "fifo_name", "/var/run/kamailio/kamailio_rpc.fifo") +/* set the path to RPC unix socket control file */ +modparam("jsonrpcs", "dgram_socket", "/var/run/kamailio/kamailio_rpc.sock") + +# -- rr params -- +# add value to ;lr param to make some broken UAs happy +modparam("rr", "enable_full_lr", 1) + +# -- cdp params -- +modparam("cdp","config_file","/etc/kamailio_icscf/icscf.xml") + +# ----- icscf params ----- +# Comment the following line to enable realm routing +#!ifdef CXDX_FORCED_PEER +modparam("ims_icscf", "cxdx_forced_peer", CXDX_FORCED_PEER) +#!endif +modparam("ims_icscf","cxdx_dest_realm", NETWORKNAME) + +# DB-URL, where information about S-CSCF-Server can be found: +#!ifdef DB_URL2 +modparam("ims_icscf", "db_url", "cluster://cluster1") +#!else +modparam("ims_icscf", "db_url", DB_URL) +#!endif + +#!ifdef PEERING +# Route which is executed, in case HSS returned "User-Unknown" on LIR request +modparam("ims_icscf","route_lir_user_unknown", "lir_term_user_unknown") +#!endif +#!ifdef FALLBACK_AUTH +# Route which is executed, in case HSS returned "User-Unknown" on UAR request +modparam("ims_icscf","route_uar_user_unknown", "uar_term_user_unknown") +#!endif + +#!ifdef WITH_TLS +# ----- tls params ----- +modparam("tls", "config", "/etc/kamailio_icscf/tls.cfg") +#!endif + +#!ifdef WITH_XMLRPC +# ----- xmlrpc params ----- +modparam("xmlrpc", "route", "XMLRPC"); +modparam("xmlrpc", "url_match", "^/RPC") +#!endif + +# ----- ctl params ----- +modparam("ctl", "binrpc", "unix:/var/run/kamailio/kamailio_ctl") + +#!ifdef WITH_DEBUG +# ----- debugger params ----- +modparam("debugger", "mod_hash_size", 5) +modparam("debugger", "mod_level_mode", 1) +modparam("debugger", "mod_level", "xlog=3") +modparam("debugger", "mod_level", "cdp=3") +modparam("debugger", "mod_level", "ims_icscf=3") +#!ifdef WITH_DEBUG_TRACE +modparam("debugger", "cfgtrace", 1) +#!endif +#!endif + +#!ifdef CAPTURE_NODE +# Destination, where to send the traffic +modparam("siptrace", "duplicate_uri", CAPTURE_NODE) +# Trace all traffic +modparam("siptrace", "trace_on", 1) +modparam("siptrace", "trace_to_database", 0) +modparam("siptrace", "trace_flag", FLT_CAPTURE) +modparam("siptrace", "hep_mode_on", 1) +#!endif + +#!ifdef PEERING +# ----- enum params ----- +modparam("enum", "domain_suffix", ENUM_SUFFIX) +#!endif + +# ----- tm params ----- +# auto-discard branches from previous serial forking leg +modparam("tm", "failure_reply_mode", 3) +# default retransmission timeout: 10sec +modparam("tm", "fr_timer", 10000) +# default invite retransmission timeout after 1xx: 120sec +modparam("tm", "fr_inv_timer", 120000) +# Don't reply automatically with "100 Trying" +modparam("tm", "auto_inv_100", 0) + +#!ifdef WITH_DEBUG +#loadmodule "debugger.so" +modparam("debugger", "mod_hash_size", 5) +modparam("debugger", "mod_level_mode", 1) +modparam("debugger", "mod_level", "cdp=3") +modparam("debugger", "mod_level", "ims_icscf=3") +#!endif + +# ------------------------- request routing logic ------------------- +# main routing logic + +route{ +#!ifdef WITH_DEBUG + xlog("I-CSCF >>>>>>>>>>>>>>>>>>>> $rm $ru ($fu => $tu ($si:$sp) to $tu, $ci)\n"); +#!endif + +# if !($rU =~ "\+.*") { +# prefix("+"); +# } + + # per request initial checks + route(REQINIT); + + if (is_method("REGISTER")) { + route(register); + } + + if (is_method("NOTIFY") && search("^(Event|o)([ \t]*):([ \t]*)reg")) { + if (!t_relay()) { + sl_reply_error(); + } + exit; + } + + if (is_method("INVITE|SUBSCRIBE|MESSAGE|INFO|PUBLISH|CANCEL")) { + route(initial_request); + } else { + # Shouldn't get here unless missconfigured (add more methods as initial) or + # somebody is routing unknown messages + append_to_reply("Allow: INVITE,SUBSCRIBE,MESSAGE,INFO,PUBLISH,CANCEL\r\n"); + send_reply("406","Initial Request Method not allowed at the I-CSCF"); + break; + } +} + +###################################################################### +# Helper routes (Basic-Checks, NAT-Handling/RTP-Control, XML-RPC) +###################################################################### +# Per SIP request initial checks +route[REQINIT] { + $var(used) = 1 - ($stat(free_size) / $stat(total_size)); + xlog("L_DBG", "Mem: Total $stat(total_size), Free $stat(free_size) [$var(used)% used]\n"); + if ($var(used) > 95) { + send_reply("503", "Server overloaded"); + exit; + } + + + # Trace this message +#!ifdef CAPTURE_NODE + sip_trace(); + setflag(FLT_CAPTURE); +#!endif + if (!mf_process_maxfwd_header("10")) { + sl_send_reply("483","Too Many Hops"); + exit; + } + if(!sanity_check("1511", "7")) { + xlog("Malformed SIP message from $si:$sp\n"); + exit; + } + + # Check for shutdown mode: + if (!has_totag() && ($sel(cfg_get.system.shutdownmode) > 0)) { + send_reply("503", "Server shutting down"); + exit; + } + + # Reply to OPTIONS: + if (is_method("OPTIONS") && (uri==myself)) { + options_reply(); + exit; + } + + # Ignore Re-Transmits: + if (t_lookup_request()) { + exit; + } + + if (is_method("INVITE|REGISTER")) { + send_reply("100", "Trying"); + } +} + +###################################################################### +# XMLRPC routing +###################################################################### +#!ifdef WITH_XMLRPC +route[XMLRPC] { + if ((method=="POST" || method=="GET") +#!ifdef XMLRPC_WHITELIST_1 +&& ((src_ip == XMLRPC_WHITELIST_1) +#!ifdef XMLRPC_WHITELIST_2 + || (src_ip == XMLRPC_WHITELIST_2) +#!endif +#!ifdef XMLRPC_WHITELIST_3 + || (src_ip == XMLRPC_WHITELIST_3) +#!endif +) +#!endif +) { + # close connection only for xmlrpclib user agents (there is a bug in + # xmlrpclib: it waits for EOF before interpreting the response). + if ($hdr(User-Agent) =~ "xmlrpclib") + set_reply_close(); + set_reply_no_connect(); + dispatch_rpc(); + exit; + } + send_reply("403", "Forbidden"); + exit; +} +#!endif + +###################################################################### +# Handling of REGISTER requests +###################################################################### +route[register] +{ + t_set_fr(5000, 5000); + #first check if we have an S-CSCF list + if (I_scscf_select("0")) { + #there is an S-CSCF list - no need to do a UAR + t_on_reply("register_reply"); + t_on_failure("register_failure"); + if (!t_relay()) { + send_reply("500","Error forwarding towards S-CSCF"); + } + } else { + #no S-CSCF list therefore must do UAR + #free this from the failed I_scscf_select call + I_scscf_drop(); + # Do an asynchronous UAR: + #0=REG/DEREG; 1=REG+Capabilities + if (!I_perform_user_authorization_request("REG_UAR_REPLY","0")) { + send_reply("500", "Error in Request"); + } + } + exit; +} + +route[REG_UAR_REPLY] +{ + #xlog("$$avp(s:uaa_return_code) = $avp(s:uaa_return_code)\n"); + #this is async so to know status we have to check the reply avp + switch ($avp(s:uaa_return_code)) { + case 1: #success + if (I_scscf_select("0")) { + t_on_failure("register_failure"); + t_on_reply("register_reply"); + #now relay to appropriate SCSCF + if (!t_relay()) { + t_reply("500", "Error forwarding to SCSCF"); + } + } else { #select failed + I_scscf_drop(); + t_reply("500", "Server error on SCSCF Select (UAR)"); + } + break; + case -1: #failure + xlog("L_ERR", "UAR failure - error response sent from module\n"); + break; + case -2: #error + xlog("L_ERR", "UAR error - sending error response now\n"); + t_reply("500", "UAR failed"); + break; + default: + xlog("L_ERR", "Unknown return code from UAR, value is [$avp(s:uaa_return_code)]\n"); + t_reply("500", "Unknown response code from UAR"); + break; + } +} + + +###################################################################### +# Replies to REGISTER requests, +###################################################################### +onreply_route[register_reply] +{ + xlog("L_DBG", "Enter register reply block"); + if (!t_check_status("(408)|(480)")){ + if (!t_check_status("(401)")){ + xlog("L_DBG", "dropping scscf list on register failure"); + I_scscf_drop(); + } else { + xlog("L_DBG", "This is a 401 - keep scscf list to do optimisation"); + } + } + break; +} + +###################################################################### +# Failed REGISTERs +###################################################################### +failure_route[register_failure] +{ + if (t_branch_timeout() || t_check_status("([5-6][0-9][0-9])")){ + if (I_scscf_select("1")) { + t_on_reply("register_reply"); + t_on_failure("register_failure"); + if (!t_relay()) { + t_reply("500","Error forwarding towards next S-CSCF"); + break; + } + break; + } else { + t_reply("500", "Server error on UAR select next S-CSCF"); + break; + } + } else { + if (!t_check_status("(401)")){ + xlog("L_DBG", "dropping scscf list on register failure"); + I_scscf_drop(); + } else { + xlog("L_DBG", "This is a 401 - keep scscf list to do optimisation"); + } + break; + } +} + +###################################################################### +# Initial requests +###################################################################### +route[initial_request] +{ +# $avp(prefix)="+"; +# $ru= $(ru{s.rm,$avp(prefix)}); + xlog("$$ru => $ru\n"); + I_perform_location_information_request("LIR_REPLY", "0"); +} + +route[LIR_REPLY] { + if ($avp(lia_return_code) == 1) { + if (I_scscf_select("0")) { + xlog("L_DBG", "ru = $ru, du = $du\n"); + t_on_reply("initial_request_reply"); + t_on_failure("initial_request_failure"); + if (!t_relay()) { + t_reply("500","Error forwarding towards S-CSCF"); + break; + } + break; + } else { + xlog("L_DBG", "dropping scscf list on initial request"); + I_scscf_drop(); + t_reply("500", "Server error on LIR select S-CSCF"); + break; + } + } else { + t_reply("500", "Server error on LIR"); + break; + } + break; +} + +###################################################################### +# Replies to initial requests +###################################################################### +onreply_route[initial_request_reply] +{ + xlog("L_DBG", "Enter initial request request block"); + if (!t_check_status("(408)")){ + xlog("L_DBG", "dropping scscf list on initial request reply"); + I_scscf_drop(); + } + break; +} + +###################################################################### +# Failed initial requests +###################################################################### +failure_route[initial_request_failure] +{ + xlog("L_DBG", "Enter initial request failure block"); + if (t_check_status("(408)")){ + xlog("L_DBG", "Got a failure for initial request"); + if (I_scscf_select("1")) { + t_on_reply("initial_request_reply"); + t_on_failure("initial_request_failure"); + if (!t_relay()) { + t_reply("500","Error forwarding towards next S-CSCF"); + break; + } + break; + } else { + t_reply("500", "Server error on LIR select next S-CSCF"); + break; + } + } else { + xlog("L_DBG", "dropping scscf list on initial request failure"); + I_scscf_drop(); + } + break; +} + +#!ifdef PEERING +###################################################################### +# HSS returned "User-Unknown" on LIR request +###################################################################### +route[lir_term_user_unknown] +{ + if (uri =~ "tel:.*") { + # Let's check, if the number can be found in ENUM: + if(!enum_query()) { + # ENUM failed, send it to the PSTN-Gateway: + route(PSTN); + break; + } + + # ENUM resolved to another domain + if ($rd != NETWORKNAME) { + t_on_reply("initial_request_reply"); + t_on_failure("initial_request_failure"); + if (!t_relay()) { + t_reply("500","Error forwarding to external domain"); + exit; + }; + exit; + } else { + t_reply("604","Does not exist anywhere - HSS User Unknown"); + exit; + }; + } else { + # we received a request for our domain (non-tel), but HSS said "User Unknown" + if ($rd != NETWORKNAME) { + t_reply("604","Does not exist anywhere - HSS User Unknown"); + exit; + } else { + # try to forward non-tel request to other domain + t_on_reply("initial_request_reply"); + t_on_failure("initial_request_failure"); + if (!t_relay()) { + t_reply("500","Error forwarding to external domain"); + exit; + }; + exit; + }; + }; +} + +###################################################################### +# Send calls to the PSTN-Gateways: +###################################################################### +route[PSTN] +{ + t_on_failure("PSTN_failure"); + # Relay the request towards the PSTN-Gateway: + if (!ds_select_dst("1", "4")) { + send_reply("503", "Service not available"); + exit; + } + # Relay the request: + if (!t_relay()) { + send_reply("503", "Service not available"); + exit; + }; + exit; +} + +###################################################################### +# manage failure routing cases, perform failover +###################################################################### +failure_route[PSTN_failure] { + # Choose another gateway, in case we + # - get a local generated "408" + # - receive a 5xx or 6xx reply from the proxy. + if (t_branch_timeout() || t_check_status("[5-6]..")) { + if (ds_next_dst()) { + # Do Failover in case problems: + t_on_failure("PSTN_failure"); + # Relay the request: + if (!t_relay()) { + send_reply("503", "Service not available"); + exit; + }; + } else { + # Add a header, to indicate the phone should try again in 30 seconds. + append_hf("Retry-After: 30\r\n"); + send_reply("503", "Service not available"); + } + exit; + } +} +#!endif + +#!ifdef FALLBACK_AUTH +###################################################################### +# HSS returned "User-Unknown" on UAR request, +# try to send it to any S-CSCF for authentication +###################################################################### +route[uar_term_user_unknown] +{ + $rd = "scscf."+NETWORKNAME; + t_on_reply("register_reply"); + t_on_failure("register_failure"); + if (!t_relay()) { + t_reply("500","Error forwarding towards S-CSCF"); + break; + } + break; +} +#!endif diff --git a/ims_base/Dockerfile b/ims_base/Dockerfile new file mode 100644 index 0000000..89338ba --- /dev/null +++ b/ims_base/Dockerfile @@ -0,0 +1,53 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM ubuntu:focal + +ENV DEBIAN_FRONTEND=noninteractive + +# Install updates and dependencies +RUN apt-get update && \ + apt-get -y install mysql-server tcpdump screen tmux ntp ntpdate git-core dkms \ + gcc flex bison libmysqlclient-dev make libssl-dev libcurl4-openssl-dev \ + libxml2-dev libpcre2-dev bash-completion g++ autoconf libmnl-dev \ + libsctp-dev libradcli-dev libradcli4 libjson-c-dev pkg-config iproute2 net-tools \ + iputils-ping libgcrypt20-dev libjansson-dev libevent-dev libnghttp2-dev uuid-dev + +# Fetch Kamailio code +RUN mkdir -p /usr/local/src/ && cd /usr/local/src/ && \ + git clone https://github.com/kamailio/kamailio && \ + cd kamailio && git checkout ba13699faba8938ff547a34af9f05631d0b8a9cd + +# Build and Install Kamailio +RUN cd /usr/local/src/kamailio && make cfg +COPY modules.lst /usr/local/src/kamailio/src +RUN cd /usr/local/src/kamailio && \ + make -j`nproc` Q=0 all | tee make_all.txt && \ + make install | tee make_install.txt && \ + ldconfig + +COPY kamailio_init.sh / +CMD ["/kamailio_init.sh"] diff --git a/ims_base/kamailio_init.sh b/ims_base/kamailio_init.sh new file mode 100755 index 0000000..34c31ee --- /dev/null +++ b/ims_base/kamailio_init.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +if [[ -z "$COMPONENT_NAME" ]]; then + echo "Error: COMPONENT_NAME environment variable not set"; exit 1; +elif [[ "$COMPONENT_NAME" =~ ^(icscf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/icscf/${COMPONENT_NAME}_init.sh && \ + mkdir -p /var/run/kamailio_icscf && \ + rm -f /kamailio_icscf.pid && \ + kamailio -f /etc/kamailio_icscf/kamailio_icscf.cfg -P /kamailio_icscf.pid -DD -E -e +elif [[ "$COMPONENT_NAME" =~ ^(scscf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/scscf/${COMPONENT_NAME}_init.sh && \ + mkdir -p /var/run/kamailio_scscf && \ + rm -f /kamailio_scscf.pid && \ + kamailio -f /etc/kamailio_scscf/kamailio_scscf.cfg -P /kamailio_scscf.pid -DD -E -e +elif [[ "$COMPONENT_NAME" =~ ^(pcscf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/pcscf/${COMPONENT_NAME}_init.sh && \ + mkdir -p /var/run/kamailio_pcscf && \ + rm -f /kamailio_pcscf.pid && \ + kamailio -f /etc/kamailio_pcscf/kamailio_pcscf.cfg -P /kamailio_pcscf.pid -DD -E -e +elif [[ "$COMPONENT_NAME" =~ ^(smsc[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/smsc/${COMPONENT_NAME}_init.sh && \ + mkdir -p /var/run/kamailio_smsc && \ + rm -f /kamailio_smsc.pid && \ + kamailio -f /etc/kamailio_smsc/kamailio_smsc.cfg -P /kamailio_smsc.pid -DD -E -e +else + echo "Error: Invalid component name: '$COMPONENT_NAME'" +fi diff --git a/ims_base/modules.lst b/ims_base/modules.lst new file mode 100644 index 0000000..05bb372 --- /dev/null +++ b/ims_base/modules.lst @@ -0,0 +1,24 @@ +# this file is autogenerated by make modules-cfg + +# the list of sub-directories with modules +modules_dirs:=modules + +# the list of module groups to compile +cfg_group_include= + +# the list of extra modules to compile +include_modules= cdp cdp_avp db_mysql dialplan enum http_async_client http_client ims_auth ims_charging ims_dialog ims_diameter_server ims_icscf ims_ipsec_pcscf ims_isc ims_ocs ims_qos ims_registrar_pcscf ims_registrar_scscf ims_usrloc_pcscf ims_usrloc_scscf jansson json nghttp2 outbound presence presence_conference presence_dialoginfo presence_mwi presence_profile presence_reginfo presence_xml pua pua_bla pua_dialoginfo pua_reginfo pua_rpc pua_usrloc pua_xmpp sctp tls utils uuid xcap_client xcap_server xmlops xmlrpc + +# the list of static modules +static_modules= + +# the list of modules to skip from compile list +skip_modules= + +# the list of modules to exclude from compile list +exclude_modules= malloc_test app_sqlang acc_json acc_radius app_java app_lua app_lua_sr app_mono app_perl app_python app_python3 app_python3s app_ruby app_ruby_proc auth_ephemeral auth_identity auth_radius cnxcc cplc crypto db2_ldap db_berkeley db_cassandra db_mongodb db_oracle db_perlvdb db_postgres db_redis db_sqlite db_unixodbc dnssec erlang evapi geoip geoip2 gzcompress h350 ims_qos_npn janssonrpcc jsonrpcc jwt kafka kazoo lcr ldap log_systemd lost lwsc memcached microhttpd misc_radius mqtt msrp nats ndb_cassandra ndb_mongodb ndb_redis nsq osp peering phonenum presence_dfks print rabbitmq regex rls rtp_media_server ruxc secsipid secsipid_proc slack snmpstats stirshaken systemdops tls_wolfssl tlsa topos_redis websocket xhttp_pi xmpp $(skip_modules) + +modules_all= $(filter-out modules/CVS modules/CMakeLists.txt, $(wildcard modules/*)) +modules_noinc= $(filter-out $(addprefix modules/, $(exclude_modules) $(static_modules)), $(modules_all)) +modules= $(filter-out $(modules_noinc), $(addprefix modules/, $(include_modules) )) $(modules_noinc) +modules_configured:=1 diff --git a/metrics/Dockerfile b/metrics/Dockerfile new file mode 100644 index 0000000..3630d5e --- /dev/null +++ b/metrics/Dockerfile @@ -0,0 +1,38 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM ubuntu:focal + +ENV DEBIAN_FRONTEND=noninteractive + +ENV PROMETHEUS_VERSION=2.55.0 + +RUN apt-get update && \ + apt-get install -y wget && \ + wget -q https://github.com/prometheus/prometheus/releases/download/v$PROMETHEUS_VERSION/prometheus-$PROMETHEUS_VERSION.linux-$(dpkg --print-architecture).tar.gz && \ + tar xvfz prometheus-$PROMETHEUS_VERSION.linux-$(dpkg --print-architecture).tar.gz + +CMD /mnt/metrics/metrics_init.sh diff --git a/metrics/metrics_init.sh b/metrics/metrics_init.sh new file mode 100755 index 0000000..49bbe70 --- /dev/null +++ b/metrics/metrics_init.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +export PROMETHEUS_WORK_DIR=prometheus-$PROMETHEUS_VERSION.linux-$(dpkg --print-architecture) +cd $PROMETHEUS_WORK_DIR + +mkdir -p /config + +cp /mnt/metrics/prometheus.yml /config/ + +sed -i 's|AMF_IP|'$AMF_IP'|g' /config/prometheus.yml +sed -i 's|SMF_IP|'$SMF_IP'|g' /config/prometheus.yml +sed -i 's|MME_IP|'$MME_IP'|g' /config/prometheus.yml +sed -i 's|PCF_IP|'$PCF_IP'|g' /config/prometheus.yml +sed -i 's|UPF_IP|'$UPF_IP'|g' /config/prometheus.yml + +./prometheus --config.file=/config/prometheus.yml diff --git a/metrics/prometheus.yml b/metrics/prometheus.yml new file mode 100644 index 0000000..41770bc --- /dev/null +++ b/metrics/prometheus.yml @@ -0,0 +1,22 @@ +global: + scrape_interval: 5s + + external_labels: + monitor: 'open5gs-monitor' + +scrape_configs: + - job_name: 'amf' + static_configs: + - targets: ['AMF_IP:9091'] + - job_name: 'smf' + static_configs: + - targets: ['SMF_IP:9091'] + - job_name: 'pcf' + static_configs: + - targets: ['PCF_IP:9091'] + - job_name: 'upf' + static_configs: + - targets: ['UPF_IP:9091'] + - job_name: 'mme' + static_configs: + - targets: ['MME_IP:9091'] diff --git a/mme/make_certs.sh b/mme/make_certs.sh new file mode 100755 index 0000000..c500418 --- /dev/null +++ b/mme/make_certs.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +if [ 1 -ne $# ] +then + echo You must specify output directory : ./make_certs.sh ./freeDiameter + + exit; +fi + +rm -rf demoCA +mkdir demoCA +echo 01 > demoCA/serial +touch demoCA/index.txt.attr +touch demoCA/index.txt + +# Generate .rnd if it does not exist +openssl rand -out /root/.rnd -hex 256 + +# CA self certificate +openssl req -new -batch -x509 -days 3650 -nodes -newkey rsa:1024 -out $1/cacert.pem -keyout cakey.pem -subj /CN=ca.EPC_DOMAIN/C=KO/ST=Seoul/L=Nowon/O=Open5GS/OU=Tests + +#mme +openssl genrsa -out $1/mme.key.pem 1024 +openssl req -new -batch -out mme.csr.pem -key $1/mme.key.pem -subj /CN=mme.EPC_DOMAIN/C=KO/ST=Seoul/L=Nowon/O=Open5GS/OU=Tests +openssl ca -cert $1/cacert.pem -days 3650 -keyfile cakey.pem -in mme.csr.pem -out $1/mme.cert.pem -outdir . -batch + +rm -rf demoCA +rm -f 01.pem 02.pem 03.pem 04.pem +rm -f cakey.pem +rm -f mme.csr.pem diff --git a/mme/mme.conf b/mme/mme.conf new file mode 100644 index 0000000..6fc8fa6 --- /dev/null +++ b/mme/mme.conf @@ -0,0 +1,266 @@ +# This is a sample configuration file for freeDiameter daemon. + +# Most of the options can be omitted, as they default to reasonable values. +# Only TLS-related options must be configured properly in usual setups. + +# It is possible to use "include" keyword to import additional files +# e.g.: include "/etc/freeDiameter.d/*.conf" +# This is exactly equivalent as copy & paste the content of the included file(s) +# where the "include" keyword is found. + + +############################################################## +## Peer identity and realm + +# The Diameter Identity of this daemon. +# This must be a valid FQDN that resolves to the local host. +# Default: hostname's FQDN +#Identity = "aaa.koganei.freediameter.net"; +Identity = "mme.EPC_DOMAIN"; + +# The Diameter Realm of this daemon. +# Default: the domain part of Identity (after the first dot). +#Realm = "koganei.freediameter.net"; +Realm = "EPC_DOMAIN"; + +############################################################## +## Transport protocol configuration + +# The port this peer is listening on for incoming connections (TCP and SCTP). +# Default: 3868. Use 0 to disable. +#Port = 3868; + +# The port this peer is listening on for incoming TLS-protected connections (TCP and SCTP). +# See TLS_old_method for more information about TLS flavours. +# Note: we use TLS/SCTP instead of DTLS/SCTP at the moment. This will change in future version of freeDiameter. +# Default: 5868. Use 0 to disable. +#SecPort = 5868; + +# Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA exchange is completed +# on the unsecure connection. The alternative is RFC6733 mechanism, where TLS protects also the +# CER/CEA exchange on a dedicated secure port. +# This parameter only affects outgoing connections. +# The setting can be also defined per-peer (see Peers configuration section). +# Default: use RFC6733 method with separate port for TLS. +#TLS_old_method; + +# Disable use of TCP protocol (only listen and connect over SCTP) +# Default : TCP enabled +#No_TCP; + +# Disable use of SCTP protocol (only listen and connect over TCP) +# Default : SCTP enabled +#No_SCTP; +# This option is ignored if freeDiameter is compiled with DISABLE_SCTP option. + +# Prefer TCP instead of SCTP for establishing new connections. +# This setting may be overwritten per peer in peer configuration blocs. +# Default : SCTP is attempted first. +#Prefer_TCP; + +# Default number of streams per SCTP associations. +# This setting may be overwritten per peer basis. +# Default : 30 streams +#SCTP_streams = 30; + +############################################################## +## Endpoint configuration + +# Disable use of IP addresses (only IPv6) +# Default : IP enabled +#No_IP; + +# Disable use of IPv6 addresses (only IP) +# Default : IPv6 enabled +#No_IPv6; + +# Specify local addresses the server must bind to +# Default : listen on all addresses available. +#ListenOn = "202.249.37.5"; +#ListenOn = "2001:200:903:2::202:1"; +#ListenOn = "fe80::21c:5ff:fe98:7d62%eth0"; +ListenOn = "MME_IP"; + + +############################################################## +## Server configuration + +# How many Diameter peers are allowed to be connecting at the same time ? +# This parameter limits the number of incoming connections from the time +# the connection is accepted until the first CER is received. +# Default: 5 unidentified clients in paralel. +#ThreadsPerServer = 5; + +############################################################## +## TLS Configuration + +# TLS is managed by the GNUTLS library in the freeDiameter daemon. +# You may find more information about parameters and special behaviors +# in the relevant documentation. +# http://www.gnu.org/software/gnutls/manual/ + +# Credentials of the local peer +# The X509 certificate and private key file to use for the local peer. +# The files must contain PKCS-1 encoded RSA key, in PEM format. +# (These parameters are passed to gnutls_certificate_set_x509_key_file function) +# Default : NO DEFAULT +#TLS_Cred = "" , ""; +#TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key"; +TLS_Cred = "/open5gs/install/etc/freeDiameter/mme.cert.pem", "/open5gs/install/etc/freeDiameter/mme.key.pem"; + +# Certificate authority / trust anchors +# The file containing the list of trusted Certificate Authorities (PEM list) +# (This parameter is passed to gnutls_certificate_set_x509_trust_file function) +# The directive can appear several times to specify several files. +# Default : GNUTLS default behavior +#TLS_CA = ""; +TLS_CA = "/open5gs/install/etc/freeDiameter/cacert.pem"; + +# Certificate Revocation List file +# The information about revoked certificates. +# The file contains a list of trusted CRLs in PEM format. They should have been verified before. +# (This parameter is passed to gnutls_certificate_set_x509_crl_file function) +# Note: openssl CRL format might have interoperability issue with GNUTLS format. +# Default : GNUTLS default behavior +#TLS_CRL = ""; + +# GNU TLS Priority string +# This string allows to configure the behavior of GNUTLS key exchanges +# algorithms. See gnutls_priority_init function documentation for information. +# You should also refer to the Diameter required TLS support here: +# http://tools.ietf.org/html/rfc6733#section-13.1 +# Default : "NORMAL" +# Example: TLS_Prio = "NONE:+VERS-TLS1.1:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL"; +#TLS_Prio = "NORMAL"; + +# Diffie-Hellman parameters size +# Set the number of bits for generated DH parameters +# Valid value should be 768, 1024, 2048, 3072 or 4096. +# (This parameter is passed to gnutls_dh_params_generate2 function, +# it usually should match RSA key size) +# Default : 1024 +#TLS_DH_Bits = 1024; + +# Alternatively, you can specify a file to load the PKCS#3 encoded +# DH parameters directly from. This accelerates the daemon start +# but is slightly less secure. If this file is provided, the +# TLS_DH_Bits parameters has no effect. +# Default : no default. +#TLS_DH_File = ""; + + +############################################################## +## Timers configuration + +# The Tc timer of this peer. +# It is the delay before a new attempt is made to reconnect a disconnected peer. +# The value is expressed in seconds. The recommended value is 30 seconds. +# Default: 30 +#TcTimer = 30; + +# The Tw timer of this peer. +# It is the delay before a watchdog message is sent, as described in RFC 3539. +# The value is expressed in seconds. The default value is 30 seconds. Value must +# be greater or equal to 6 seconds. See details in the RFC. +# Default: 30 +#TwTimer = 30; + +############################################################## +## Applications configuration + +# Disable the relaying of Diameter messages? +# For messages not handled locally, the default behavior is to forward the +# message to another peer if any is available, according to the routing +# algorithms. In addition the "0xffffff" application is advertised in CER/CEA +# exchanges. +# Default: Relaying is enabled. +NoRelay; + +# Number of server threads that can handle incoming messages at the same time. +# Default: 4 +#AppServThreads = 4; + +# Other applications are configured by loaded extensions. + +############################################################## +## Extensions configuration + +# The freeDiameter framework merely provides support for +# Diameter Base Protocol. The specific application behaviors, +# as well as advanced functions, are provided +# by loadable extensions (plug-ins). +# These extensions may in addition receive the name of a +# configuration file, the format of which is extension-specific. +# +# Format: +#LoadExtension = "/path/to/extension" [ : "/optional/configuration/file" ] ; +# +# Examples: +#LoadExtension = "extensions/sample.fdx"; +#LoadExtension = "extensions/sample.fdx":"conf/sample.conf"; + +# Extensions are named as follow: +# dict_* for extensions that add content to the dictionary definitions. +# dbg_* for extensions useful only to retrieve more information on the framework execution. +# acl_* : Access control list, to control which peers are allowed to connect. +# rt_* : routing extensions that impact how messages are forwarded to other peers. +# app_* : applications, these extensions usually register callbacks to handle specific messages. +# test_* : dummy extensions that are useful only in testing environments. + + +# The dbg_msg_dump.fdx extension allows you to tweak the way freeDiameter displays some +# information about some events. This extension does not actually use a configuration file +# but receives directly a parameter in the string passed to the extension. Here are some examples: +## LoadExtension = "dbg_msg_dumps.fdx" : "0x1111"; # Removes all default hooks, very quiet even in case of errors. +## LoadExtension = "dbg_msg_dumps.fdx" : "0x2222"; # Display all events with few details. +## LoadExtension = "dbg_msg_dumps.fdx" : "0x0080"; # Dump complete information about sent and received messages. +# The four digits respectively control: connections, routing decisions, sent/received messages, errors. +# The values for each digit are: +# 0 - default - keep the default behavior +# 1 - quiet - remove any specific log +# 2 - compact - display only a summary of the information +# 4 - full - display the complete information on a single long line +# 8 - tree - display the complete information in an easier to read format spanning several lines. + +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dbg_msg_dumps.fdx" : "0x8888"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_rfc5777.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_mip6i.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_nasreq.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_nas_mipv6.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_dcca.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_dcca_3gpp.fdx"; + + +############################################################## +## Peers configuration + +# The local server listens for incoming connections. By default, +# all unknown connecting peers are rejected. Extensions can override this behavior (e.g., acl_wl). +# +# In addition to incoming connections, the local peer can +# be configured to establish and maintain connections to some +# Diameter nodes and allow connections from these nodes. +# This is achieved with the ConnectPeer directive described below. +# +# Note that the configured Diameter Identity MUST match +# the information received inside CEA, or the connection will be aborted. +# +# Format: +#ConnectPeer = "diameterid" [ { parameter1; parameter2; ...} ] ; +# Parameters that can be specified in the peer's parameter list: +# No_TCP; No_SCTP; No_IP; No_IPv6; Prefer_TCP; TLS_old_method; +# No_TLS; # assume transparent security instead of TLS. DTLS is not supported yet (will change in future versions). +# Port = 5868; # The port to connect to +# TcTimer = 30; +# TwTimer = 30; +# ConnectTo = "202.249.37.5"; +# ConnectTo = "2001:200:903:2::202:1"; +# TLS_Prio = "NORMAL"; +# Realm = "realm.net"; # Reject the peer if it does not advertise this realm. +# Examples: +#ConnectPeer = "aaa.wide.ad.jp"; +#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; Port=3868; } ; +ConnectPeer = "hss.EPC_DOMAIN" { ConnectTo = "HSS_IP"; Port = 3868; No_TLS; }; + + +############################################################## diff --git a/mme/mme.yaml b/mme/mme.yaml new file mode 100644 index 0000000..a89c398 --- /dev/null +++ b/mme/mme.yaml @@ -0,0 +1,60 @@ +logger: + file: + path: /open5gs/install/var/log/open5gs/mme.log + +global: + max: + ue: MAX_NUM_UE + +mme: + freeDiameter: /open5gs/install/etc/freeDiameter/mme.conf + s1ap: + server: + - dev: MME_IF + gtpc: + server: + - dev: MME_IF + client: + sgwc: + - address: SGWC_IP + smf: + - address: SMF_IP + sgsap: + client: + - address: OSMOMSC_IP + local_address: MME_IP + map: + tai: + plmn_id: + mcc: MCC + mnc: MNC + tac: TAC + lai: + plmn_id: + mcc: MCC + mnc: MNC + lac: 1 + gummei: + - plmn_id: + mcc: MCC + mnc: MNC + mme_gid: 2 + mme_code: 1 + tai: + - plmn_id: + mcc: MCC + mnc: MNC + tac: TAC + security: + integrity_order : [ EIA2, EIA1, EIA0 ] + ciphering_order : [ EEA0, EEA1, EEA2 ] + network_name: + full: DHI + mme_name: open5gs-mme0 + metrics: + server: + - address: MME_IP + port: 9091 + time: + t3412: + value: 540 diff --git a/mme/mme_init.sh b/mme/mme_init.sh new file mode 100755 index 0000000..a5d3bd1 --- /dev/null +++ b/mme/mme_init.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) +export IF_NAME=$(ip r | awk '/default/ { print $5 }') + +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +cp /mnt/mme/mme.yaml install/etc/open5gs +cp /mnt/mme/mme.conf install/etc/freeDiameter +cp /mnt/mme/make_certs.sh install/etc/freeDiameter + +sed -i 's|MNC|'$MNC'|g' install/etc/open5gs/mme.yaml +sed -i 's|MCC|'$MCC'|g' install/etc/open5gs/mme.yaml +sed -i 's|TAC|'$TAC'|g' install/etc/open5gs/mme.yaml +sed -i 's|MME_IP|'$MME_IP'|g' install/etc/open5gs/mme.yaml +sed -i 's|MME_IF|'$IF_NAME'|g' install/etc/open5gs/mme.yaml +sed -i 's|OSMOMSC_IP|'$OSMOMSC_IP'|g' install/etc/open5gs/mme.yaml +sed -i 's|SGWC_IP|'$SGWC_IP'|g' install/etc/open5gs/mme.yaml +sed -i 's|SMF_IP|'$SMF_IP'|g' install/etc/open5gs/mme.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/mme.yaml +sed -i 's|MME_IP|'$MME_IP'|g' install/etc/freeDiameter/mme.conf +sed -i 's|HSS_IP|'$HSS_IP'|g' install/etc/freeDiameter/mme.conf +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' install/etc/freeDiameter/mme.conf +sed -i 's|LD_LIBRARY_PATH|'$LD_LIBRARY_PATH'|g' install/etc/freeDiameter/mme.conf +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' install/etc/freeDiameter/make_certs.sh + +# Generate TLS certificates +./install/etc/freeDiameter/make_certs.sh install/etc/freeDiameter + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/mysql/Dockerfile b/mysql/Dockerfile new file mode 100644 index 0000000..837367e --- /dev/null +++ b/mysql/Dockerfile @@ -0,0 +1,40 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM ubuntu:focal + +ENV DEBIAN_FRONTEND=noninteractive + +# Install updates and dependencies +RUN apt-get update && \ + apt-get -y install mysql-server ca-certificates + +ADD mysql_init.sh /mysql_init.sh +RUN chmod 755 /mysql_init.sh + +RUN /etc/init.d/mysql stop + +CMD /mysql_init.sh diff --git a/mysql/mysql_init.sh b/mysql/mysql_init.sh new file mode 100755 index 0000000..22a671c --- /dev/null +++ b/mysql/mysql_init.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +sed -i "s/127.0.0.1/0.0.0.0/g" /etc/mysql/mysql.conf.d/mysqld.cnf +sed -i "s/# max_connections = 151/max_connections = 250/g" /etc/mysql/mysql.conf.d/mysqld.cnf +cat > ~/.my.cnf < /etc/timezone + +# Grant privileges and set max connections +ROOT_USER_EXISTS=`mysql -u root -s -N -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE User = 'root' AND Host = '%')"` +if [[ "$ROOT_USER_EXISTS" == 0 ]] +then + mysql -u root -e "CREATE USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'ims'"; + mysql -u root -e "GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION"; + mysql -u root -e "ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY ''" + mysql -u root -e "FLUSH PRIVILEGES;" +fi + +pkill -9 mysqld +sleep 5 +mysqld_safe diff --git a/nr-gnb.yaml b/nr-gnb.yaml new file mode 100644 index 0000000..18652e5 --- /dev/null +++ b/nr-gnb.yaml @@ -0,0 +1,29 @@ +version: '3' +services: + nr_gnb: + image: docker_ueransim + container_name: nr_gnb + stdin_open: true + tty: true + volumes: + - ./ueransim:/mnt/ueransim + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=ueransim-gnb + expose: + - "38412/sctp" + - "2152/udp" + - "4997/udp" + cap_add: + - NET_ADMIN + privileged: true + networks: + default: + ipv4_address: ${NR_GNB_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/nr-ue.yaml b/nr-ue.yaml new file mode 100644 index 0000000..7fb2dc7 --- /dev/null +++ b/nr-ue.yaml @@ -0,0 +1,27 @@ +version: '3' +services: + nr_ue: + image: docker_ueransim + container_name: nr_ue + stdin_open: true + tty: true + volumes: + - ./ueransim:/mnt/ueransim + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + environment: + - COMPONENT_NAME=ueransim-ue + expose: + - "4997/udp" + cap_add: + - NET_ADMIN + privileged: true + networks: + default: + ipv4_address: ${NR_UE_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/nrf/nrf.yaml b/nrf/nrf.yaml new file mode 100644 index 0000000..6005127 --- /dev/null +++ b/nrf/nrf.yaml @@ -0,0 +1,23 @@ +logger: + file: + path: /open5gs/install/var/log/open5gs/nrf.log + +sbi: + server: + no_tls: true + client: + no_tls: true + +global: + max: + ue: MAX_NUM_UE + +nrf: + serving: # 5G roaming requires PLMN in NRF + - plmn_id: + mcc: MCC + mnc: MNC + sbi: + server: + - address: NRF_IP + port: 7777 diff --git a/nrf/nrf_init.sh b/nrf/nrf_init.sh new file mode 100755 index 0000000..2854e1c --- /dev/null +++ b/nrf/nrf_init.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +cp /mnt/nrf/nrf.yaml install/etc/open5gs +sed -i 's|NRF_IP|'$NRF_IP'|g' install/etc/open5gs/nrf.yaml +sed -i 's|SCP_IP|'$SCP_IP'|g' install/etc/open5gs/nrf.yaml +sed -i 's|MCC|'$MCC'|g' install/etc/open5gs/nrf.yaml +sed -i 's|MNC|'$MNC'|g' install/etc/open5gs/nrf.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/nrf.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/nssf/nssf.yaml b/nssf/nssf.yaml new file mode 100644 index 0000000..a72228c --- /dev/null +++ b/nssf/nssf.yaml @@ -0,0 +1,29 @@ +logger: + file: + path: /open5gs/install/var/log/open5gs/nssf.log + +sbi: + server: + no_tls: true + client: + no_tls: true + +global: + max: + ue: MAX_NUM_UE + +nssf: + sbi: + server: + - address: NSSF_IP + port: 7777 + client: + nrf: + - uri: http://NRF_IP:7777 + scp: + - uri: http://SCP_IP:7777 + nsi: + - uri: http://NRF_IP:7777 + s_nssai: + sst: 1 + diff --git a/nssf/nssf_init.sh b/nssf/nssf_init.sh new file mode 100755 index 0000000..3417de4 --- /dev/null +++ b/nssf/nssf_init.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +cp /mnt/nssf/nssf.yaml install/etc/open5gs +sed -i 's|NSSF_IP|'$NSSF_IP'|g' install/etc/open5gs/nssf.yaml +sed -i 's|NRF_IP|'$NRF_IP'|g' install/etc/open5gs/nssf.yaml +sed -i 's|SCP_IP|'$SCP_IP'|g' install/etc/open5gs/nssf.yaml +sed -i 's|NRF_IP|'$NRF_IP'|g' install/etc/open5gs/nssf.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/nssf.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/oai/enb.band7.tm1.50PRB.usrpb210.conf b/oai/enb.band7.tm1.50PRB.usrpb210.conf new file mode 100644 index 0000000..735fdf4 --- /dev/null +++ b/oai/enb.band7.tm1.50PRB.usrpb210.conf @@ -0,0 +1,315 @@ +Active_eNBs = ( "eNB-Eurecom-LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB-Eurecom-LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ( { mcc = MCC; mnc = MNC; mnc_length = MNC_LEN; } ); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "3GPP_eNODEB"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2685000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = -27; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; + + //Parameters for SIB18 + rxPool_sc_CP_Len = "normal"; + rxPool_sc_Period = "sf40"; + rxPool_data_CP_Len = "normal"; + rxPool_ResourceConfig_prb_Num = 20; + rxPool_ResourceConfig_prb_Start = 5; + rxPool_ResourceConfig_prb_End = 44; + rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + rxPool_ResourceConfig_offsetIndicator_choice = 0; + rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; +/* rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; +*/ + // Parameters for SIB19 + discRxPool_cp_Len = "normal" + discRxPool_discPeriod = "rf32" + discRxPool_numRetx = 1; + discRxPool_numRepetition = 2; + discRxPool_ResourceConfig_prb_Num = 5; + discRxPool_ResourceConfig_prb_Start = 3; + discRxPool_ResourceConfig_prb_End = 21; + discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + discRxPool_ResourceConfig_offsetIndicator_choice = 0; + discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "MME_IP"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + enable_measurement_reports = "no"; + + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "OAI_ENB_IF"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "OAI_ENB_IP"; + ENB_INTERFACE_NAME_FOR_S1U = "OAI_ENB_IF"; + ENB_IPV4_ADDRESS_FOR_S1U = "OAI_ENB_IP"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + + ENB_IPV4_ADDRESS_FOR_X2C = "OAI_ENB_IP"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + + } +); + +DU = ( + { + DU_INTERFACE_NAME_FOR_F1U = "lo"; + DU_IPV4_ADDRESS_FOR_F1U = "127.0.0.1/16"; + DU_PORT_FOR_F1U = 22100; + F1_U_DU_TRANSPORT_TYPE = "TCP"; + } + ); + +CU = ( + { + CU_INTERFACE_NAME_FOR_F1U = "lo"; + CU_IPV4_ADDRESS_FOR_F1U = "127.0.0.1"; //Address to search the DU + CU_PORT_FOR_F1U = 22100; + F1_U_CU_TRANSPORT_TYPE = "TCP"; // One of TCP/UDP/SCTP + DU_TYPE = "LTE"; + }//, +// { +// CU_INTERFACE_NAME_FOR_F1U = "eth0"; +// CU_IPV4_ADDRESS_FOR_F1U = "10.64.93.142"; //Address to search the DU +// CU_PORT_FOR_F1U = 2211; +// F1_U_CU_TRANSPORT_TYPE = "TCP"; // One of TCP/UDP/SCTP +// DU_TYPE = "WiFi"; +// } + ); + + CU_BALANCING = "ALL"; + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + puSch10xSnr = 200; + puCch10xSnr = 200; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 125; + eNB_instances = [0]; + + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "lo"; + FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +/* +#example config for rfsimulator +rfsimulator : +{ + serveraddr = "enb"; + serverport = "4043"; + options = ("saviq"); + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; +*/ + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/oai/enb_dockerfile b/oai/enb_dockerfile new file mode 100644 index 0000000..b45b6ba --- /dev/null +++ b/oai/enb_dockerfile @@ -0,0 +1,54 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM ubuntu:focal + +ENV DEBIAN_FRONTEND=noninteractive +ENV BUILD_UHD_FROM_SOURCE=True +ENV UHD_VERSION=4.4.0.0 + +# Install updates and dependencies +RUN apt-get update && \ + apt-get -y install build-essential cmake git subversion software-properties-common apt-utils unzip xxd iproute2 + +# Install SoapySDR and Lime Suite +RUN apt-get update && \ + apt-get -y install limesuite liblimesuite-dev limesuite-udev \ + soapysdr-tools soapysdr-module-lms7 + +# Cloning RAN repository (eNB RAN + UE RAN) +RUN git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git && \ + cd openairinterface5g/ && git checkout v2.1.0 + +# Set the working directory to openairinterface5g +WORKDIR openairinterface5g + +RUN . ./oaienv && cd cmake_targets && \ + ./build_oai -I -w USRP --eNB --verbose-compile + + +CMD . ./oaienv && /mnt/oai/oai_init.sh && cd cmake_targets/ran_build/build && \ + ./lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -d diff --git a/oai/gnb.sa.band41.fr1.52PRB.usrpb210.conf b/oai/gnb.sa.band41.fr1.52PRB.usrpb210.conf new file mode 100644 index 0000000..0a2e21e --- /dev/null +++ b/oai/gnb.sa.band41.fr1.52PRB.usrpb210.conf @@ -0,0 +1,288 @@ +# This file is derived from ./phy-demo/oai/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.24PRB.usrpb210.conf +# ./nr-uesoftmodem -r 24 --numerology 1 --band 41 -C 2593320000 --ssb 24 --rfsim --sa + +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = MCC; mnc = MNC; mnc_length = MNC_LEN; snssaiList = ({ sst = 1 }) }); + + nr_cellid = 12345678L; + + ////////// Physical parameters: + + do_CSIRS = 1; + do_SRS = 1; + sib1_tda = 15; + min_rxtxtime = 6; + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 6; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 2574.270 MHz + 53 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 518670; + dl_frequencyBand = 41; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 517734; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 0; + dl_carrierBandwidth = 52; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=106 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 14025; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 0; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 6; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 41; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 0; + ul_carrierBandwidth = 52; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 14025; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 0; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 0, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 0; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 0; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 7; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "AMF_IP"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_NG_AMF = "OAI_ENB_IF"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "OAI_ENB_IP"; + GNB_INTERFACE_NAME_FOR_NGU = "OAI_ENB_IF"; + GNB_IPV4_ADDRESS_FOR_NGU = "OAI_ENB_IP"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; + ulsch_max_frame_inactivity = 1; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 150; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( +{ + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [41]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + sf_extension = 0; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + clock_src = "internal"; +} +); + +THREAD_STRUCT = ( +{ + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; +} +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = "4043"; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + ngap_log_level ="debug"; + ngap_log_verbosity ="medium"; +}; + diff --git a/oai/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/oai/gnb.sa.band78.fr1.106PRB.usrpb210.conf new file mode 100644 index 0000000..b9eb844 --- /dev/null +++ b/oai/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -0,0 +1,267 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = MCC; mnc = MNC; mnc_length = MNC_LEN; snssaiList = ({ sst = 1; }) }); + + nr_cellid = 12345678L; + + ////////// Physical parameters: + + do_CSIRS = 1; + do_SRS = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "AMF_IP"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_NG_AMF = "OAI_ENB_IF"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "OAI_ENB_IP"; + GNB_INTERFACE_NAME_FOR_NGU = "OAI_ENB_IF"; + GNB_IPV4_ADDRESS_FOR_NGU = "OAI_ENB_IP"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; + ulsch_max_frame_inactivity = 0; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 100; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( +{ + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0; + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + clock_src = "internal"; +} +); + +THREAD_STRUCT = ( +{ + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; +} +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = "4043"; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="debug"; +}; + diff --git a/oai/gnb_dockerfile b/oai/gnb_dockerfile new file mode 100644 index 0000000..d202c71 --- /dev/null +++ b/oai/gnb_dockerfile @@ -0,0 +1,53 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM ubuntu:jammy + +ENV DEBIAN_FRONTEND=noninteractive +ENV BUILD_UHD_FROM_SOURCE=True +ENV UHD_VERSION=4.4.0.0 + +# Install updates and dependencies +RUN apt-get update && \ + apt-get -y install build-essential cmake git subversion software-properties-common apt-utils unzip xxd iproute2 + +# Install SoapySDR and Lime Suite +RUN apt-get update && \ + apt-get -y install limesuite liblimesuite-dev limesuite-udev \ + soapysdr-tools soapysdr-module-lms7 + +# Cloning RAN repository (eNB RAN + UE RAN) +RUN git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git && \ + cd openairinterface5g/ && git checkout v2.1.0 + +# Set the working directory to openairinterface5g +WORKDIR openairinterface5g + +RUN . ./oaienv && cd cmake_targets && \ + ./build_oai -I -w USRP --gNB --verbose-compile + +CMD . ./oaienv && /mnt/oai/oai_init.sh && cd cmake_targets/ran_build/build && \ + ./nr-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.52PRB.usrpb210.conf --sa -d diff --git a/oai/oai_init.sh b/oai/oai_init.sh new file mode 100755 index 0000000..5ee2406 --- /dev/null +++ b/oai/oai_init.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) +export IF_NAME=$(ip r | awk '/default/ { print $5 }') + +cp /mnt/oai/enb.band7.tm1.50PRB.usrpb210.conf $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/ +cp /mnt/oai/gnb.sa.band78.fr1.106PRB.usrpb210.conf $OPENAIR_DIR/targets/PROJECTS/GENERIC-NR-5GC/CONF/ +cp /mnt/oai/gnb.sa.band41.fr1.52PRB.usrpb210.conf $OPENAIR_DIR/targets/PROJECTS/GENERIC-NR-5GC/CONF/ + +[ ${#MNC} == 3 ] && MNC_LEN=3 || MNC_LEN=2 + +ENB_CONF_FILE="enb.band7.tm1.50PRB.usrpb210.conf" +GNB_CONF_FILE="gnb.sa.band41.fr1.52PRB.usrpb210.conf" + +sed -i 's|MNC_LEN|'$MNC_LEN'|g' $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/$ENB_CONF_FILE +sed -i 's|MNC|'$MNC'|g' $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/$ENB_CONF_FILE +sed -i 's|MCC|'$MCC'|g' $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/$ENB_CONF_FILE +sed -i 's|OAI_ENB_IF|'$IF_NAME'|g' $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/$ENB_CONF_FILE +sed -i 's|OAI_ENB_IP|'$OAI_ENB_IP'|g' $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/$ENB_CONF_FILE +sed -i 's|MME_IP|'$MME_IP'|g' $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/$ENB_CONF_FILE + +sed -i 's|MNC_LEN|'$MNC_LEN'|g' $OPENAIR_DIR/targets/PROJECTS/GENERIC-NR-5GC/CONF/$GNB_CONF_FILE +sed -i 's|MNC|'$MNC'|g' $OPENAIR_DIR/targets/PROJECTS/GENERIC-NR-5GC/CONF/$GNB_CONF_FILE +sed -i 's|MCC|'$MCC'|g' $OPENAIR_DIR/targets/PROJECTS/GENERIC-NR-5GC/CONF/$GNB_CONF_FILE +sed -i 's|OAI_ENB_IF|'$IF_NAME'|g' $OPENAIR_DIR/targets/PROJECTS/GENERIC-NR-5GC/CONF/$GNB_CONF_FILE +sed -i 's|OAI_ENB_IP|'$OAI_ENB_IP'|g' $OPENAIR_DIR/targets/PROJECTS/GENERIC-NR-5GC/CONF/$GNB_CONF_FILE +sed -i 's|AMF_IP|'$AMF_IP'|g' $OPENAIR_DIR/targets/PROJECTS/GENERIC-NR-5GC/CONF/$GNB_CONF_FILE + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/oaienb.yaml b/oaienb.yaml new file mode 100644 index 0000000..f55d7bf --- /dev/null +++ b/oaienb.yaml @@ -0,0 +1,34 @@ +version: '3' +services: + oaienb: + build: + context: oai + dockerfile: enb_dockerfile + image: docker_oai_enb + container_name: oaienb + stdin_open: true + tty: true + privileged: true + sysctls: + - net.ipv4.ip_forward=1 + devices: + - "/dev/bus" + volumes: + - /dev/serial:/dev/serial:ro + - /dev/bus/usb:/dev/bus/usb:ro + - ./oai:/mnt/oai + - ./log:/openairinterface5g/cmake_targets/log/ + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + expose: + - "36412/sctp" + - "2152/udp" + networks: + default: + ipv4_address: ${OAI_ENB_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/oaignb.yaml b/oaignb.yaml new file mode 100644 index 0000000..430a342 --- /dev/null +++ b/oaignb.yaml @@ -0,0 +1,34 @@ +version: '3' +services: + oaignb: + build: + context: oai + dockerfile: gnb_dockerfile + image: docker_oai_gnb + container_name: oaignb + stdin_open: true + tty: true + privileged: true + sysctls: + - net.ipv4.ip_forward=1 + devices: + - "/dev/bus" + volumes: + - /dev/serial:/dev/serial:ro + - /dev/bus/usb:/dev/bus/usb:ro + - ./oai:/mnt/oai + - ./log:/openairinterface5g/cmake_targets/log/ + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + expose: + - "38412/sctp" + - "2152/udp" + networks: + default: + ipv4_address: ${OAI_ENB_IP} +networks: + default: + external: + name: docker_open5gs_default diff --git a/ocs/Dockerfile b/ocs/Dockerfile new file mode 100644 index 0000000..3d2e5e1 --- /dev/null +++ b/ocs/Dockerfile @@ -0,0 +1,31 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM sigscale/ocs:3.4.41-1 + +ENV DEBIAN_FRONTEND=noninteractive + +ENTRYPOINT /mnt/ocs/ocs_init.sh diff --git a/ocs/ocs_init.sh b/ocs/ocs_init.sh new file mode 100755 index 0000000..8fdfd58 --- /dev/null +++ b/ocs/ocs_init.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" +export NODENAME=ocs@$EPC_DOMAIN + +if test -z "$RELDIR"; then + export RELDIR=$HOME/releases +fi +START_ERL_DATA=$RELDIR/start_erl.data +RELEASENAME=`sed 's/^.* //' $START_ERL_DATA` + +cp /mnt/ocs/start ./bin/ +cp /mnt/ocs/sys.config ./releases/$RELEASENAME/ + +OCS_COMMA_SEPARATED_IP="${OCS_IP//./,}" +SMF_COMMA_SEPARATED_IP="${SMF_IP//./,}" + +sed -i 's|OCS_IP|'$OCS_IP'|g' ./releases/$RELEASENAME/sys.config +sed -i 's|OCS_COMMA_SEPARATED_IP|'$OCS_COMMA_SEPARATED_IP'|g' ./releases/$RELEASENAME/sys.config +sed -i 's|SMF_COMMA_SEPARATED_IP|'$SMF_COMMA_SEPARATED_IP'|g' ./releases/$RELEASENAME/sys.config +sed -i 's|SMF_IF|'$SMF_IF'|g' ./releases/$RELEASENAME/sys.config +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' ./releases/$RELEASENAME/sys.config +sed -i 's|OCS_BIND_PORT|'$OCS_BIND_PORT'|g' ./releases/$RELEASENAME/sys.config +sed -i 's|RELEASENAME|'$RELEASENAME'|g' ./releases/$RELEASENAME/sys.config + +./bin/initialize + +exec ./bin/start $@ + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/ocs/start b/ocs/start new file mode 100755 index 0000000..8f74b25 --- /dev/null +++ b/ocs/start @@ -0,0 +1,48 @@ +#!/bin/bash +# +# SigScale Global Inc. +# +# Start Erlang/OTP Embedded system. +# +# Usage: start [Erlang Emulator Flags] + +if test -z "$NODENAME"; then + export NODENAME=ocs +fi + +if test -z "$ERL_LIBS"; then + export ERL_LIBS=lib +fi + +if test -z "$ROOTDIR"; then + export ROOTDIR=/usr/lib/erlang +fi + +if test -z "$RELDIR"; then + export RELDIR=$HOME/releases +fi +START_ERL_DATA=$RELDIR/start_erl.data + +if test -n "$ERLANG_COOKIE"; then + if ! test -e ~/.erlang.cookie; then + echo -n $ERLANG_COOKIE > ~/.erlang.cookie + chmod 400 ~/.erlang.cookie + fi +fi + +if test $# -gt 0; then + ERLARGS="$*" + shift $# +else + ERLARGS="+K true +Bi -boot_var OTPHOME ${ROOTDIR} -noinput -name ${NODENAME} ${ERLARGS}" +fi + +echo "ERLARGS: $ERLARGS" + +if test -n "$ERL_RPC"; then + ERLARGS="$ERLARGS -kernel inet_dist_listen_min $ERL_RPC -kernel inet_dist_listen_max $ERL_RPC" +fi + +export TERM=xterm + +exec ${ROOTDIR}/bin/start_erl ${ROOTDIR} ${RELDIR} ${START_ERL_DATA} ${ERLARGS} diff --git a/ocs/sys.config b/ocs/sys.config new file mode 100644 index 0000000..2e284ce --- /dev/null +++ b/ocs/sys.config @@ -0,0 +1,82 @@ +[{ocs, + [ + {diameter, + [{ + acct, + [{ + {OCS_COMMA_SEPARATED_IP}, OCS_BIND_PORT, + [ + {'Origin-Host', "ocs.EPC_DOMAIN"}, + {'Origin-Realm', "EPC_DOMAIN"}, + {'Host-IP-Address', "OCS_IP"}, + {'Auth-Application-Id', [4]}, + {sub_id_type, [imsi, msisdn]} + ] + }] + }] + }, + {acct_log_rotate, 1440}, + {acct_log_rotate_time, {4,4,4}}, + {acct_log_dir, "log/acct"}, + {auth_log_dir, "log/auth"}, + {abmf_log_dir, "log/abmf"}, + {ipdr_log_dir, "log/ipdr"}, + {export_dir, "log/export"}, + {tls_key, "ssl/key.pem"}, + {tls_cert, "ssl/cert.pem"}, + {tls_cacert, "ssl/ca.pem"}]}, +{radius, + [{sock_opts, [{recbuf, 131072}, {sndbuf, 131072}]}]}, +{mnesia, + [{dir, "db"}]}, +{snmp, + [{agent, + [{config, [{dir, "snmp/conf"}]}, + {db_dir, "snmp/db"}]}]}, +{inets, + [{services, + [{httpd, + [{server_name, "ocs"}, + {directory_index, ["index.html"]}, + {directory, {"/health", []}}, + {directory, {"/partyRoleManagement", []}}, + {directory, {"/", + [{auth_type, mnesia}, + {auth_name, "ocs.sigscale.org"}, + {require_group, ["staff"]}]}}, + {transfer_disk_log, "log/http/transfer"}, + {security_disk_log, "log/http/security"}, + {error_disk_log, "log/http/error"}, + {transfer_disk_log_size, {10485760, 10}}, + {error_disk_log_size, {10485760, 10}}, + {security_disk_log_size, {10485760, 10}}, + {disk_log_format, internal}, + {modules, + [mod_alias, + mod_auth, + mod_responsecontrol, + mod_ocs_rest_accepted_content, + mod_ocs_rest_get, + mod_get, + mod_ocs_rest_head, + mod_ocs_rest_post, + mod_ocs_rest_patch, + mod_ocs_rest_delete, + mod_disk_log]}, + {mime_types, + [{"html", "text/html"}, + {"css", "text/css"}, + {"js", "application/javascript"}, + {"json", "application/json"}, + {"svg", "image/svg+xml"}, + {"png", "image/png"}, + {"csv", "text/csv"}]}, + {port, 8083}, + {socket_type, ip_comm}, +% {socket_type, {essl, +% [{certfile, "ssl/cert.pem"}, +% {keyfile, "ssl/key.pem"}]}}, + {server_root, "./"}, + {alias, {"/doc", "lib/RELEASENAME/doc"}}, + {alias, {"/schema", "lib/RELEASENAME/priv/schema"}}, + {document_root, "lib/RELEASENAME/priv/www"}]}]}]}]. diff --git a/opensips_ims_base/Dockerfile b/opensips_ims_base/Dockerfile new file mode 100644 index 0000000..a9c417d --- /dev/null +++ b/opensips_ims_base/Dockerfile @@ -0,0 +1,52 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM debian:bullseye + +ENV DEBIAN_FRONTEND=noninteractive + +# Install updates and dependencies +RUN apt-get update && \ + apt-get -y install tcpdump git gcc flex bison make pkg-config iproute2 net-tools iputils-ping \ + libssl-dev libcurl4-openssl-dev libxml2-dev libpcre2-dev bash-completion g++ autoconf \ + libmnl-dev libsctp-dev libradcli-dev libradcli4 libjson-c-dev libevent-dev libnghttp2-dev uuid-dev \ + libfreediameter-dev default-libmysqlclient-dev libpcre3-dev libmicrohttpd-dev librabbitmq-dev \ + libncurses-dev mariadb-client + +# Fetch OpenSIPS code +RUN mkdir -p /usr/local && cd /usr/local && \ + git clone https://github.com/OpenSIPS/opensips && \ + cd opensips && git checkout tags/3.5.5 + +# Build and Install OpenSIPS +COPY Makefile.conf /usr/local/opensips +RUN cd /usr/local/opensips && \ + make -j`nproc` all | tee make_all.txt && \ + make install | tee make_install.txt && \ + ldconfig + +COPY opensips_init.sh / +CMD ["/opensips_init.sh"] diff --git a/opensips_ims_base/Makefile.conf b/opensips_ims_base/Makefile.conf new file mode 100644 index 0000000..4c0a38f --- /dev/null +++ b/opensips_ims_base/Makefile.conf @@ -0,0 +1,126 @@ +#aaa_diameter= Diameter implementation for the core AAA API | freeDiameter (libfdcore + libfdproto) v1.2.1 or higher +#aaa_radius= Radius implementation for the core AAA API | Radius client development library, typically radiusclient-ng 0.5.0 or higher +#auth_jwt= JWT auth support | JWT client development library, libjwt-dev +#cachedb_cassandra= Implementation of a cache system designed to work with Cassandra servers | thrift 0.6.1 +#cachedb_couchbase= Implementation of a cache system designed to work with CouchBase servers | libcouchbase >= 2.0 +#cachedb_dynamodb= Implementation of a cache system designed to work with Dynamodb servers | libaws-cpp-sdk-core and libaws-cpp-sdk-dynamodb +#cachedb_memcached= Implementation of a cache system designed to work with a memcached server. | Memcached client library, typically libmemcached +#cachedb_mongodb= Implementation of a cache system designed to work with a MongoDB server. | libjson and the mongo-c-driver +#cachedb_redis= Implementation of a cache system designed to work with Redis servers | Redis client library, hiredis +#carrierroute= Provides routing, balancing and blacklisting capabilities. | libconfuse, a configuration file parser library +#cgrates= Provides integration with the CGRateS billing/rating engine. | JSON library, libjson +#compression= Implements SIP message compression/decompression and base64 encoding | zlib dev library, typically zlib1g-dev +#cpl_c= Implements a CPL (Call Processing Language) interpreter | library for parsing XML files, typically libxml2 and libxml2-devel +#db_berkeley= Integrates the Berkeley DB into OpenSIPS | Berkeley embedded database +#db_http= Provides access to a database that is implemented as a HTTP server. | CURL library - libcurl +#db_mysql= Provides MySQL connectivity for OpenSIPS | development libraries of mysql-client , typically libmysqlclient-dev +#db_oracle= Provides Oracle connectivity for OpenSIPS. | Development library of OCI, typically instantclient-sdk-10.2.0.3 +#db_perlvdb= Provides a virtualization framework for OpenSIPS's database access. | Perl library development files, typically libperl-dev +#db_postgres= Provides Postgres connectivity for OpenSIPS | PostgreSQL library and development library - typically libpq5 and libpq-dev +#db_sqlite= Provides SQLite connectivity for OpenSIPS | SQLite library and development library - typically libsqlite3 and libsqlite3-dev +#db_unixodbc= Allows to use the unixodbc package with OpenSIPS | ODBC library and ODBC development library +#dialplan= Implements generic string translations based on matching and replacement rules | PCRE development library, typically libpcre-dev +#emergency= Provides emergency call treatment for OpenSIPS | CURL dev library - typically libcurl4-openssl-dev +#event_rabbitmq= Provides the implementation of a RabbitMQ client for the Event Interface | RabbitMQ development library, librabbitmq-dev +#event_kafka= Provides the implementation of an Apache Kafka producer for the Event Interface | Kafka development library, librdkafka-dev +#h350= Enables access to SIP account data stored in an LDAP [RFC4510] directory containing H.350 commObjects | OpenLDAP library & development files, typically libldap and libldap-dev +#regex= Offers matching operations against regular expressions using the powerful PCRE library. | Development library for PCRE, typically libpcre-dev +#identity= Adds support for SIP Identity (see RFC 4474). | SSL library, typically libssl +#jabber= Integrates XODE XML parser for parsing Jabber messages | Expat library. +#json= Introduces a new type of variable that provides both serialization and de-serialization from JSON format. | JSON library, libjson +#launch_darkly= Implements an interface to the Launch Darkly feature management cloud | Launch Darkly C++ server-side SDK (libldserverapi) +#ldap= Implements an LDAP search interface for OpenSIPS | OpenLDAP library & development files, typically libldap and libldap-dev +#lua= Easily implement your own OpenSIPS extensions in Lua | liblua5.1-0-dev, libmemcache-dev and libmysqlclient-dev +#httpd= Provides an HTTP transport layer implementation for OpenSIPS. | libmicrohttpd +#http2d= Provides HTTP/2 server-side support, using nghttp2 | nghttp2 library (libnghttp2), libevent, libssl and libevent-openssl +#mi_xmlrpc_ng= New version of the xmlrpc server that handles xmlrpc requests and generates xmlrpc responses. | parsing/building XML library, typically libxml +#mmgeoip= Lightweight wrapper for the MaxMind GeoIP API | libGeoIP +#osp= Enables OpenSIPS to support secure, multi-lateral peering using the OSP standard | OSP development kit, typically osptoolkit +#perl= Easily implement your own OpenSIPS extensions in Perl | Perl library development files, typically libperl-dev +#pi_http= Provides a simple web database provisioning interface | XML parsing & building library, typically libxml-dev +#rabbitmq_consumer= Receive AMQP messages which will be delivered by triggering events | RabbitMQ development library, librabbitmq-dev +#proto_ipsec= Provides support for IPSec sockets in OpenSIPS | Library used for Netlink communication with kernel, libmnl-dev +#proto_sctp= Provides support for SCTP listeners in OpenSIPS | SCTP development library, typically libsctp-dev +#proto_tls= Provides support for TLS listeners in OpenSIPS | SSL development library, typically libssl-dev +#proto_wss= Provides support for Secure WebSocket listeners in OpenSIPS | SSL development library, typically libssl-dev +#presence= Handles PUBLISH and SUBSCRIBE messages and generates NOTIFY messages in a general, event independent way | XML parsing & Building library, typically libxml-dev +#presence_dialoginfo= Enables the handling of "Event: dialog" (as defined in RFC 4235) | XML parsing & building library, typically libxml-dev +#presence_mwi= Does specific handling for notify-subscribe message-summary (message waiting indication) events as specified in RFC 3842 | XML parsing & building library, typically libxml-dev +#presence_reginfo= Presence handler for "reg"-events according to RFC 3680 | XML parsing & building library,typically libxml-dev +#presence_xml= Does specific handling for notify-subscribe events using xml bodies. | XML parsing & building library, typically libxml-dev +#presence_dfks = Does specific handling for DFKS (as-feature-event) events. | XML parsing & building library, typically libxml-dev +#pua= Offers the functionality of a presence user agent client, sending Subscribe and Publish messages. | XML parsing & building library, typically libxml-dev +#pua_bla= Enables Bridged Line Appearances support according | XML parsing & building library, typically libxml-dev +#pua_dialoginfo= Retrieves dialog state information from the dialog module and PUBLISHes the dialog-information using the pua module. | XML parsing & building library,typically libxml-dev +#pua_mi= Offers the possibility to publish presence information and subscribe to presence information via MI transports. | XML parsing & building library,typically libxml-dev +#pua_reginfo= Publisher for "reg"-events according to RFC 3680 | XML parsing & building library,typically libxml-dev +#pua_usrloc= Connector between usrloc and pua modules. | XML parsing & building library,typically libxml-dev +#pua_xmpp= Gateway for presence between SIP and XMPP. | XML parsing & building library,typically libxml-dev +#python= Easily implement your own OpenSIPS extensions in Python | Shared Python runtime library, libpython +#rest_client= Simple HTTP client | CURL library - libcurl +#rls= Resource List Server implementation following the specification in RFC 4662 and RFC 4826 | parsing/building XML library, typically libxml-dev +#sngtc= Voice Transcoding using the D-series Sangoma transcoding cards | libsngtc_node +#siprec= SIP Call Recording to an external/passive recorder | uuid-dev +#snmpstats= Provides an SNMP management interface to OpenSIPS | NetSNMP v5.3 +#tls_openssl= Implements TLS operations using the OpenSSL libarary | SSL development library, typically libssl-dev +#tls_mgm= Provides a TLS interface to manage certificates for OpenSIPS | +#tls_wolfssl= Implements TLS operations using the wolfSSL libarary | +#xcap= XCAP utility functions for OpenSIPS. | libxml-dev +#xcap_client= XCAP client for OpenSIPS.It fetches XCAP elements, either documents or part of them, by sending HTTP GET requests | libxml-dev and libcurl-dev +#xml= Introduces a new type of variable that provides both serialization and de-serialization from XML format. | XML library, libxml2-dev +#xmpp= Gateway between OpenSIPS and a jabber server. It enables the exchange of IMs between SIP clients and XMPP(jabber) clients. | parsing/building XML files, typically libexpat1-devel +#uuid= UUID generator | uuid-dev + +exclude_modules?= aaa_radius auth_jwt b2b_logic_xml \ + cachedb_cassandra cachedb_couchbase cachedb_dynamodb cachedb_memcached \ + cachedb_mongodb cachedb_redis carrierroute cgrates compression cpl_c \ + db_berkeley db_http db_oracle db_perlvdb db_postgres db_sqlite \ + db_unixodbc emergency event_rabbitmq event_kafka event_sqs h350 \ + http2d identity jabber json launch_darkly ldap lua mi_xmlrpc_ng \ + mmgeoip osp perl pi_http presence_dialoginfo presence_mwi \ + presence_xml presence_dfks proto_sctp proto_tls \ + proto_wss pua_bla pua_dialoginfo pua_mi pua_usrloc pua_xmpp \ + python regex rabbitmq_consumer rls siprec sngtc snmpstats \ + stir_shaken tls_mgm tls_openssl tls_wolfssl uuid xcap xcap_client \ + xmpp rtp.io + +include_modules?= aaa_diameter db_mysql dialplan httpd presence presence_reginfo proto_ipsec \ + pua pua_reginfo xml signaling sl tm rr maxfwd nathelper sipmsgops mi_fifo usrloc registrar acc dispatcher \ + proto_udp proto_tcp db_text dialog rtpengine event_route json auth_aka aka_av_diameter auth \ + rest_client + +DEFS+= -DPKG_MALLOC #Use a faster malloc +DEFS+= -DSHM_MMAP #Use mmap instead of SYSV shared memory +DEFS+= -DUSE_MCAST #Compile in support for IP Multicast +DEFS+= -DDISABLE_NAGLE #Disable the TCP NAgle Algorithm ( lower delay ) +DEFS+= -DSTATISTICS #Enable the statistics manager +DEFS+= -DHAVE_RESOLV_RES #Support for changing some of the resolver parameters +# Specifying exactly 1 allocator will cause it to be inlined (fastest) +DEFS+= -DF_MALLOC #Fast memory allocator with minimal runtime overhead +DEFS+= -DQ_MALLOC #Quality assurance memory allocator with runtime safety checks +DEFS+= -DHP_MALLOC #High performance allocator with fine-grained locking +DEFS+= -DDBG_MALLOC #Include additional, debug-enabled allocator flavors +#DEFS+= -DQM_DBG_MALLOC_HIST=3 #Size of debug history for Q_MALLOC (default is 1) +#DEFS+= -DNO_DEBUG #Compile out all debug messages +#DEFS+= -DNO_LOG #Compile out all logging +#DEFS_GROUP_START +#DEFS+= -DFAST_LOCK #Use fast architecture specific locking +#DEFS+= -DUSE_SYSV_SEM #Use SYSV sems for locking ( slower & limited number of locks +#DEFS+= -DUSE_PTHREAD_MUTEX #Use pthread mutexes for locking +#DEFS+= -DUSE_UMUTEX #Use FreeBSD-specific low-level mutexes for locking +#DEFS+= -DUSE_POSIX_SEM #Use POSIX sems for locking +#DEFS_GROUP_END +#DEFS+= -DUSE_FUTEX #Use linux futexes with fast architecture specific locking +#DEFS+= -DBUSY_WAIT #Use busy waiting on the lock +#DEFS+= -DDBG_LOCK #Attach debug info to all lock structures +#DEFS+= -DDBG_TCPCON #Attach struct history info to all TCP connections +#DEFS+= -DNOSMP #Do not use SMP compliant locking. Faster but won't work on SMP machines +#DEFS+= -DEXTRA_DEBUG #Compile in some extra debugging code +DEFS+= -DCC_O0 #Zero compiler optimizations (FAST compile, SLOW code. For devs) +#DEFS+= -DORACLE_USRLOC #Use Oracle compatible queries for USRLOC +#DEFS+= -DSHM_EXTRA_STATS #Provide tools to get extra statistics for the shared memory used +#DEFS+= -DUNIT_TESTS #Include unit testing code into opensips and modules +#DEFS+= -DFUZZ_BUILD #Add extra runtime checks to prevent false-positive crashes +#DEFS+= -DPROFILING #Periodically sample each process' call stack, for profiling purposes + +PREFIX ?= /usr/local/ diff --git a/opensips_ims_base/opensips_init.sh b/opensips_ims_base/opensips_init.sh new file mode 100755 index 0000000..4e82733 --- /dev/null +++ b/opensips_ims_base/opensips_init.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +if [[ -z "$COMPONENT_NAME" ]]; then + echo "Error: COMPONENT_NAME environment variable not set"; exit 1; +elif [[ "$COMPONENT_NAME" =~ ^(icscf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/icscf/${COMPONENT_NAME}_init.sh +elif [[ "$COMPONENT_NAME" =~ ^(scscf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/scscf/${COMPONENT_NAME}_init.sh +elif [[ "$COMPONENT_NAME" =~ ^(pcscf[[:digit:]]*$) ]]; then + echo "Deploying component: '$COMPONENT_NAME'" + /mnt/pcscf/${COMPONENT_NAME}_init.sh +else + echo "Error: Invalid component name: '$COMPONENT_NAME'" +fi diff --git a/opensips_ims_icscf/freeDiameter.conf b/opensips_ims_icscf/freeDiameter.conf new file mode 100644 index 0000000..9ccbb5a --- /dev/null +++ b/opensips_ims_icscf/freeDiameter.conf @@ -0,0 +1,13 @@ +Identity = "icscf.IMS_DOMAIN"; +Realm = "IMS_DOMAIN"; +Port = ICSCF_BIND_PORT; +ListenOn = "ICSCF_IP"; +SecPort = 0; +No_SCTP; +NoRelay; + +ConnectPeer = "hss.IMS_DOMAIN" { + No_TLS; + ConnectTo = "PYHSS_IP"; + port = PYHSS_BIND_PORT; +}; diff --git a/opensips_ims_icscf/icscf.dictionary b/opensips_ims_icscf/icscf.dictionary new file mode 100644 index 0000000..a6e9f04 --- /dev/null +++ b/opensips_ims_icscf/icscf.dictionary @@ -0,0 +1,32 @@ +VENDOR 10415 TGPP + +ATTRIBUTE Visited-Network-Identifier 600 string 10415 +ATTRIBUTE Public-Identity 601 string 10415 +ATTRIBUTE Server-Name 602 string 10415 + +APPLICATION-AUTH 16777216/10415 3GPP Cx + +REQUEST 300 User-Authorization Request +{ + Session-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Realm | REQUIRED | 1 + Vendor-Specific-Application-Id | REQUIRED | 1 + Auth-Session-State | REQUIRED | 1 + User-Name | REQUIRED | 1 + Public-Identity | REQUIRED | 1 + Visited-Network-Identifier | REQUIRED | 1 +} + +ANSWER 300 User-Authorization Answer +{ + Session-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Host | OPTIONAL | 1 + Destination-Realm | OPTIONAL | 1 + Vendor-Specific-Application-Id | REQUIRED | 1 + Auth-Session-State | REQUIRED | 1 + Experimental-Result | REQUIRED | 1 +} diff --git a/opensips_ims_icscf/icscf_init.sh b/opensips_ims_icscf/icscf_init.sh new file mode 100755 index 0000000..e9a7608 --- /dev/null +++ b/opensips_ims_icscf/icscf_init.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +mkdir -p /etc/opensips +cp /mnt/icscf/freeDiameter.conf /etc/opensips +cp /mnt/icscf/icscf.dictionary /etc/opensips +cp /mnt/icscf/opensips.cfg /etc/opensips + +# For mi_fifo module. +mkdir -p /var/run/opensips + +sed -i 's|ICSCF_IP|'$ICSCF_IP'|g' /etc/opensips/freeDiameter.conf +sed -i 's|PYHSS_IP|'$PYHSS_IP'|g' /etc/opensips/freeDiameter.conf +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/opensips/freeDiameter.conf +sed -i 's|PYHSS_BIND_PORT|'$PYHSS_BIND_PORT'|g' /etc/opensips/freeDiameter.conf +sed -i 's|ICSCF_BIND_PORT|'$ICSCF_BIND_PORT'|g' /etc/opensips/freeDiameter.conf + +sed -i 's|ICSCF_IP|'$ICSCF_IP'|g' /etc/opensips/opensips.cfg +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/opensips/opensips.cfg + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +exec opensips -f /etc/opensips/opensips.cfg -F $@ diff --git a/opensips_ims_icscf/opensips.cfg b/opensips_ims_icscf/opensips.cfg new file mode 100644 index 0000000..0d8cb5a --- /dev/null +++ b/opensips_ims_icscf/opensips.cfg @@ -0,0 +1,227 @@ +# +# OpenSIPS residential configuration script +# by OpenSIPS Solutions +# +# This script was generated via "make menuconfig", from +# the "Residential" scenario. +# You can enable / disable more features / functionalities by +# re-generating the scenario with different options.# +# +# Please refer to the Core CookBook at: +# https://opensips.org/Resources/DocsCookbooks +# for a explanation of possible statements, functions and parameters. +# + + +####### Global Parameters ######### + +/* uncomment the following lines to enable debugging */ +#debug_mode=yes + +log_level=3 +xlog_level=3 +log_stderror=yes +log_stdout=yes +log_facility=LOG_LOCAL0 + +udp_workers=4 + +/* uncomment the next line to enable the auto temporary blacklisting of + not available destinations (default disabled) */ +#disable_dns_blacklist=no + +/* uncomment the next line to enable IPv6 lookup after IPv4 dns + lookup failures (default disabled) */ +#dns_try_ipv6=yes + + +socket=udp:ICSCF_IP:4060 +socket=tcp:ICSCF_IP:4060 + +alias="icscf.IMS_DOMAIN" + +#set module path +mpath="/usr/local/opensips/modules" + +####### Modules Section ######## +####### http module ###### +loadmodule "httpd.so" + +modparam("httpd", "ip", "ICSCF_IP") +modparam("httpd", "port", 8080) + + +#### SIGNALING module +loadmodule "signaling.so" + +#### StateLess module +loadmodule "sl.so" + +#### Transaction Module +loadmodule "tm.so" +modparam("tm", "fr_timeout", 5) +modparam("tm", "fr_inv_timeout", 30) +modparam("tm", "restart_fr_on_each_reply", 0) +modparam("tm", "onreply_avp_mode", 1) + +#### Record Route Module +loadmodule "rr.so" +/* do not append from tag to the RR (no need for this script) */ +modparam("rr", "append_fromtag", 0) + +#### MAX ForWarD module +loadmodule "maxfwd.so" + +#### SIP MSG OPerationS module +loadmodule "sipmsgops.so" + +#### FIFO Management Interface +loadmodule "mi_fifo.so" +modparam("mi_fifo", "fifo_name", "/var/run/opensips/opensips_fifo") +modparam("mi_fifo", "fifo_mode", 0666) + +#### USeR LOCation module +loadmodule "usrloc.so" +modparam("usrloc", "nat_bflag", "NAT") +modparam("usrloc", "working_mode_preset", "single-instance-no-db") + +#### REGISTRAR module +loadmodule "registrar.so" +modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT") +/* uncomment the next line not to allow more than 10 contacts per AOR */ +#modparam("registrar", "max_contacts", 10) + +#### ACCounting module +loadmodule "acc.so" +/* what special events should be accounted ? */ +modparam("acc", "early_media", 0) +modparam("acc", "report_cancels", 0) +/* by default we do not adjust the direct of the sequential requests. + if you enable this parameter, be sure to enable "append_fromtag" + in "rr" module */ +modparam("acc", "detect_direction", 0) + +loadmodule "proto_udp.so" +loadmodule "proto_tcp.so" + +#### aaa_diameter module +loadmodule "aaa_diameter.so" +modparam("aaa_diameter", "fd_log_level", 1) # max amount of logging, quite annoying +modparam("aaa_diameter", "realm", "IMS_DOMAIN") +modparam("aaa_diameter", "peer_identity", "hss") +modparam("aaa_diameter", "aaa_url", + "diameter:/etc/opensips/freeDiameter.conf;extra-avps-file:/etc/opensips/icscf.dictionary") + +#### JSON module +loadmodule "json.so" + + + +####### Routing Logic ######## + +# main request routing logic + +route{ + xlog("L_INFO", "[$ci] Start route time [$Tf] method ($rm) r-uri ($ru) \n"); + + if (!mf_process_maxfwd_header(10)) { + send_reply(483,"Too Many Hops"); + exit; + } + + if (has_totag()) { + + # handle hop-by-hop ACK (no routing required) + if ( is_method("ACK") && t_check_trans() ) { + t_relay(); + exit; + } + + # sequential request within a dialog should + # take the path determined by record-routing + if ( !loose_route() ) { + # we do record-routing for all our traffic, so we should not + # receive any sequential requests without Route hdr. + send_reply(404,"Not here"); + exit; + } + + if (is_method("BYE")) { + # do accounting even if the transaction fails + do_accounting("log","failed"); + } + + # route it out to whatever destination was set by loose_route() + # in $du (destination URI). + route(relay); + exit; + } + + # CANCEL processing + if (is_method("CANCEL")) { + if (t_check_trans()) + t_relay(); + exit; + } + + # absorb retransmissions, but do not create transaction + t_check_trans(); + + if (is_method("REGISTER")) { + xlog("L_INFO", "[$ci] Received REGISTER for $tu - doing UAR\n"); + + $var(payload) = "[ + { \"Session-Id\": \"icscf.IMS_DOMAIN;"+$Ts+"."+$Tsm+";"+$pp+"\" }, + { \"Origin-Host\": \"icscf.IMS_DOMAIN\" }, + { \"Origin-Realm\": \"IMS_DOMAIN\" }, + { \"Destination-Realm\": \"IMS_DOMAIN\" }, + { \"Vendor-Specific-Application-Id\": [{\"Vendor-Id\": 10415}, + {\"Auth-Application-Id\": 16777216}]}, + { \"Auth-Session-State\": 1 }, + { \"User-Name\": \""+$fU+"@"+$fd+"\" }, + { \"Public-Identity\": \""+$fu+"\" }, + { \"Visited-Network-Identifier\": \"IMS_DOMAIN\" } + ]"; + + $var(rc) = dm_send_request(16777216, 300, $var(payload), $var(rpl_avps)); + xlog("[$ci] UAA rc: $var(rc), UAA AVPs: $var(rpl_avps)\n"); + + $var(server_name) = NULL; + $json(rpl_avps) := $var(rpl_avps); + for ($var(item) in $(json(rpl_avps)[*])) { + $json(item) := $var(item); + for ($var(key) in $(json(item.keys)[*])) { + if ($var(key) == "Server-Name") { + $var(server_name) = $json(item/$var(key)); + break; + } + } + if ($var(server_name) != NULL) + break; + } + + if ($var(server_name) == NULL) { + xlog("L_ERR", "[$ci] No server available!\n"); + send_reply(503,"Not available"); + exit; + } + + # relay to S-CSCF + xlog("L_INFO", "[$ci] using S-CSCF $var(server_name)\n"); + $ru = $var(server_name); + + route(relay); + exit; + } + + send_reply(503,"Not Implemented"); + exit; +} + + +route[relay] { + if (!t_relay()) { + send_reply(500,"Internal Error"); + } + exit; +} diff --git a/opensips_ims_pcscf/db/dispatcher b/opensips_ims_pcscf/db/dispatcher new file mode 100644 index 0000000..7d833c5 --- /dev/null +++ b/opensips_ims_pcscf/db/dispatcher @@ -0,0 +1,2 @@ +id(int,auto) setid(int) destination(string) socket(string,null) state(int) probe_mode(int) weight(string) priority(int) attrs(string) description(string) +1:1:sip\:172.22.0.41\:5060:null:0:1:1:1:'carrier':'icscf' diff --git a/opensips_ims_pcscf/db/version b/opensips_ims_pcscf/db/version new file mode 100644 index 0000000..70753cc --- /dev/null +++ b/opensips_ims_pcscf/db/version @@ -0,0 +1,2 @@ +table_name(string) table_version(int) +dispatcher:9 diff --git a/opensips_ims_pcscf/freeDiameter.conf b/opensips_ims_pcscf/freeDiameter.conf new file mode 100644 index 0000000..8c554f1 --- /dev/null +++ b/opensips_ims_pcscf/freeDiameter.conf @@ -0,0 +1,13 @@ +Identity = "pcscf.IMS_DOMAIN"; +Realm = "IMS_DOMAIN"; +Port = PCSCF_BIND_PORT; +ListenOn = "PCSCF_IP"; +SecPort = 0; +No_SCTP; +NoRelay; + +ConnectPeer = "pcrf.EPC_DOMAIN" { + No_TLS; + ConnectTo = "PCRF_IP"; + port = PCRF_BIND_PORT; +}; diff --git a/opensips_ims_pcscf/opensips.cfg b/opensips_ims_pcscf/opensips.cfg new file mode 100644 index 0000000..1b90926 --- /dev/null +++ b/opensips_ims_pcscf/opensips.cfg @@ -0,0 +1,484 @@ +# +# OpenSIPS residential configuration script +# by OpenSIPS Solutions +# +# This script was generated via "make menuconfig", from +# the "Residential" scenario. +# You can enable / disable more features / functionalities by +# re-generating the scenario with different options.# +# +# Please refer to the Core CookBook at: +# https://opensips.org/Resources/DocsCookbooks +# for a explanation of possible statements, functions and parameters. +# + + +####### Global Parameters ######### + +/* uncomment the following lines to enable debugging */ +#debug_mode=yes + +log_level=6 +xlog_level=3 +#mem_log=6 +log_stderror=yes +log_stdout=yes +log_facility=LOG_LOCAL0 + +udp_workers=4 + +/* uncomment the next line to enable the auto temporary blacklisting of + not available destinations (default disabled) */ +#disable_dns_blacklist=no + +/* uncomment the next line to enable IPv6 lookup after IPv4 dns + lookup failures (default disabled) */ +#dns_try_ipv6=yes + +dns=no + +socket=udp:PCSCF_IP:5060 +socket=tcp:PCSCF_IP:5060 +socket=ipsec:PCSCF_IP:6100,5100 + +alias="pcscf.IMS_DOMAIN" + + +#set module path +mpath="/usr/local/opensips/modules" + +####### Modules Section ######## + +#### MYSQL module +loadmodule "db_mysql.so" + +#### SIGNALING module +loadmodule "signaling.so" + +#### StateLess module +loadmodule "sl.so" + +#### Transaction Module +loadmodule "tm.so" +modparam("tm", "fr_timeout", 5) +modparam("tm", "fr_inv_timeout", 30) +modparam("tm", "restart_fr_on_each_reply", 0) +modparam("tm", "onreply_avp_mode", 1) + +#### Record Route Module +loadmodule "rr.so" +/* do not append from tag to the RR (no need for this script) */ +modparam("rr", "append_fromtag", 0) + +#### MAX ForWarD module +loadmodule "maxfwd.so" + +#### NATHELPER module +loadmodule "nathelper.so" + +#### SIP MSG OPerationS module +loadmodule "sipmsgops.so" + +#### FIFO Management Interface +loadmodule "mi_fifo.so" +modparam("mi_fifo", "fifo_name", "/var/run/opensips/opensips_fifo") +modparam("mi_fifo", "fifo_mode", 0666) + +#### USeR LOCation module +loadmodule "usrloc.so" +modparam("usrloc", "nat_bflag", "NAT") +modparam("usrloc", "mi_dump_kv_store", 1) +modparam("usrloc", "working_mode_preset", "single-instance-no-db") + +#### REGISTRAR module +loadmodule "registrar.so" +modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT") +/* uncomment the next line not to allow more than 10 contacts per AOR */ +#modparam("registrar", "max_contacts", 10) + +#### ACCounting module +loadmodule "acc.so" +/* what special events should be accounted ? */ +modparam("acc", "early_media", 0) +modparam("acc", "report_cancels", 0) +/* by default we do not adjust the direct of the sequential requests. + if you enable this parameter, be sure to enable "append_fromtag" + in "rr" module */ +modparam("acc", "detect_direction", 0) + +#### proto_udp module +loadmodule "dispatcher.so" + +loadmodule "proto_udp.so" +loadmodule "proto_tcp.so" +loadmodule "proto_ipsec.so" +loadmodule "dialog.so" + +#### dbtext module +loadmodule "db_text.so" +modparam("dispatcher", "db_url", "text:///etc/opensips/db") + +#### aaa_diameter module +loadmodule "aaa_diameter.so" +modparam("aaa_diameter", "fd_log_level", 0) # max amount of logging, quite annoying +modparam("aaa_diameter", "realm", "IMS_DOMAIN") +modparam("aaa_diameter", "peer_identity", "hss") +modparam("aaa_diameter", "aaa_url", + "diameter:/etc/opensips/freeDiameter.conf;extra-avps-file:/etc/opensips/pcscf.dictionary") + +modparam("proto_ipsec", "min_spi", 10000) +modparam("proto_ipsec", "max_spi", 10100) +modparam("proto_ipsec", "allowed_algorithms", "hmac-sha-1-96=null, hmac-md5-96=null") + +#### RTPENGINE module +loadmodule "rtpengine.so" +modparam("rtpengine", "rtpengine_sock", "udp:RTPENGINE_IP:2223") + + +loadmodule "event_route.so" +loadmodule "json.so" + +#### PRESENCE modules +loadmodule "presence.so" +loadmodule "presence_reginfo.so" +loadmodule "pua.so" +modparam("pua|presence","db_url", "mysql://opensips_pcscf:heslo@MYSQL_IP/opensips_pcscf") + +loadmodule "pua_reginfo.so" + +modparam("pua_reginfo", "ul_domain", "location") +modparam("pua_reginfo", "ul_identities_key", "identities") +modparam("pua_reginfo", "default_domain", "IMS_DOMAIN") +modparam("pua_reginfo", "server_address", "sip:reginfo@pcscf.IMS_DOMAIN") + + +####### Routing Logic ######## + +# main request routing logic + +route{ + xlog("L_INFO", "[$ci] Start route time [$Tf] method ($rm) r-uri ($ru) \n"); + set_via_handling("force-rport"); + + if (!mf_process_maxfwd_header(10)) { + send_reply(483,"Too Many Hops"); + exit; + } + + if (has_totag()) { + + # handle hop-by-hop ACK (no routing required) + if ( is_method("ACK") && t_check_trans() ) { + t_relay(); + exit; + } + + # sequential request within a dialog should + # take the path determined by record-routing + if ( !loose_route() ) { + # we do record-routing for all our traffic, so we should not + # receive any sequential requests without Route hdr. + send_reply(404,"Not here"); + exit; + } + + if (is_method("BYE")) { + # do accounting even if the transaction fails + do_accounting("log","failed"); + route(session_termination); + } + + if (is_method("UPDATE")) { + if ($si != "SCSCF_IP") + rtpengine_offer("replace-origin"); + else + t_on_reply("rtpengine_answer"); + } + + if (is_method("SUBSCRIBE|NOTIFY") && is_myself($rd)) { + route(handle_presence); + exit; + } + + # route it out to whatever destination was set by loose_route() + # in $du (destination URI). + route(relay); + exit; + } + + # CANCEL processing + if (is_method("CANCEL")) { + if (t_check_trans()) + t_relay(); + exit; + } + + # absorb retransmissions, but do not create transaction + t_check_trans(); + + if (is_method("REGISTER")) { + xlog("L_INFO", "[$ci] Received REGISTER for $tu - relaying to I-CSCF\n"); + append_hf("Path: \r\n"); + + if ($hdr(Security-Client)) { + setflag("SEC_AGREE"); + append_hf("P-Visited-Network-ID: IMS_DOMAIN\r\n"); + } + + t_on_reply("register_reply"); + route(relay); + exit; + } else if (is_method("SUBSCRIBE|PUBLISH")) { + xlog("L_INFO", "[$ci] Received $rm for $tu - handling\n"); + route(handle_presence); + exit; + } else if (is_method("INVITE")) { + if (loose_route()) { + xlog("L_INFO", "[$ci] Received INVITE for $tu - relaying to S-CSCF ($ru/$du)\n"); + remove_hf("Security-Verify"); + if (list_hdr_has_option("Require", "sec-agree")) + list_hdr_remove_option("Require", "sec-agree"); + if (list_hdr_has_option("Proxy-Require", "sec-agree")) + list_hdr_remove_option("Proxy-Require", "sec-agree"); + append_hf("P-Visited-Network-ID: IMS_DOMAIN\r\n"); + $socket_out = "tcp:PCSCF_IP:5060"; + $avp(si) = $si; + rtpengine_offer("replace-origin"); + } else { + xlog("L_INFO", "[$ci] Received INVITE for $tu - looking up from S-CSCF ($ru/$du/$tu)\n"); + $rU = $(tU{s.select,0,;}); + if (!lookup("location")) { + xlog("L_ERR", "[$ci] user $rU not found\n"); + t_reply(404, "Not here"); + exit; + } + } + route(extract_ip_port); + $avp(ip) = $var(ip); + $avp(port) = $var(port); + $avp(rtcp) = $var(rtcp); + $avp(stream) = $(rb{sdp.stream,0}); + t_on_reply("invite_reply"); + if (!record_route()) { + xlog("L_ERR", "[$ci] Cannot do record_route()\n"); + t_reply(503, "Internal Error"); + exit; + } + if (!create_dialog()) { + xlog("L_ERR", "[$ci] Cannot create_dialog()\n"); + t_reply(503, "Internal Error"); + exit; + } + + if (!t_relay()) { + xlog("L_ERR", "[$ci] Cannot relay to $ru/$du\n"); + t_reply(503, "Internal Error"); + exit; + } + exit; + } + + send_reply(405,"Method Not Allowed"); + exit; +} + + +route[relay] { + if (!t_relay()) { + send_reply(500,"Internal Error"); + } + exit; +} + +onreply_route[register_reply] { + xlog("L_INFO","[$ci] Received REGISTER reply $rs from $si for $tu\n"); + if ($T_reply_code == 401) { + if (!isflagset("SEC_AGREE") || ipsec_create()) + route(dm_send_aar, "control"); + } else if ($T_reply_code == 200) { + for ($var(item) in $(hdr(P-Associated-URI)[*])) { + $var(uri_len) = $(var(item){s.len}) - 2; + $var(uri) = $(var(item){s.substr, 1, $var(uri_len)}); + if (!save("location", "no-reply, path-off", $var(uri))) { + xlog("L_ERR", "[$ci] could not save aor [$var(uri)]\n"); + } else { + ul_add_key("location", "$tU@$td", "identities", "$var(uri)"); + } + } + reginfo_update("$tU@$td"); + } +} + +onreply_route[invite_reply] { + + if (!has_body_part("application/sdp")) { + xlog("L_INFO","[$ci] Received INVITE reply $rs from $si for $tu - without SDP\n"); + return; + } else if (isflagset("INVITE_AAA")) { + xlog("L_INFO","[$ci] Received INVITE reply $rs from $si for $tu - AAA done\n"); + return; + } + xlog("L_INFO","[$ci] Received INVITE reply $rs from $si for $tu - doing AAR\n"); + route(extract_ip_port); + if ($avp(si) == NULL) { + rtpengine_answer("replace-origin"); + $avp(si) = $si; + $var(tmp_ip) = $avp(ip); + $var(tmp_port) = $avp(port); + $avp(ip) := $var(ip); + $avp(port) := $var(port); + $var(ip) = $var(tmp_ip); + $var(port) = $var(tmp_port); + } + route(dm_send_aar, "audio"); + setflag("INVITE_AAA"); +} + +onreply_route[rtpengine_answer] { + if (!has_body_part("application/sdp")) + return; + rtpengine_answer("replace-origin"); +} + + +route[dm_send_aar] { + + switch ($param(1)) { + + case "control": + if ($ipsec(ip) != NULL) { + $var(src_ip) = $ipsec_ue(ip); + $var(src_port) = $ipsec_ue(port-c); + $var(dst_ip) = $ipsec(ip); + $var(dst_port) = $ipsec(port-s); + $var(sess_port) = $ipsec_ue(port-s); + } else { + $var(src_ip) = $si; + $var(src_port) = $sp; + $var(dst_ip) = $socket_in(ip); + $var(dst_port) = $socket_in(port); + $var(sess_port) = $sp; + } + $var(media_component) = "[{\"Media-Component-Number\": 1}, + {\"Media-Sub-Component\": [{\"Flow-Number\": 1}, + {\"Flow-Description\": \"permit in ip from "+$var(src_ip)+" "+$var(src_port)+" to "+$var(dst_ip)+" "+$var(dst_port)+"\"}, + {\"Flow-Description\": \"permit out ip from "+$var(dst_ip)+" "+$var(dst_port)+" to "+$var(src_ip)+" "+$var(src_port)+"\"}, + {\"Flow-Usage\": 2}]}, + {\"Media-Type\": 4}, + {\"Codec-Data\": \"uplink\noffer\n\"}, + {\"Codec-Data\": \"downlink\nanswer\n\"}, + {\"Flow-Status\": 2}]"; + $avp(si) = $var(src_ip); + $var(session_id) = $var(src_ip) + ";" + $var(sess_port) + ";pcscf.IMS_DOMAIN;"+$Ts+"."+$Tsm+";"+$pp; + break; + case "audio": + $var(session_id) = "pcscf.IMS_DOMAIN;"+$Ts+"."+$Tsm+";"+$pp; + $var(media_component) = "[{\"Media-Component-Number\": 1}, + {\"Media-Sub-Component\": [{\"Flow-Number\": 1}, + {\"Flow-Description\": \"permit in 17 from "+$avp(ip)+" "+$avp(port)+" to "+$var(ip)+" "+$var(port)+"\"}, + {\"Flow-Description\": \"permit out 17 from "+$var(ip)+" "+$var(port)+" to "+$avp(ip)+" "+$avp(port)+"\"}, + {\"Flow-Description\": \"permit in 17 from "+$avp(ip)+" "+$avp(rtcp)+" to "+$var(ip)+" "+$var(rtcp)+"\"}, + {\"Flow-Description\": \"permit out 17 from "+$var(ip)+" "+$var(rtcp)+" to "+$avp(ip)+" "+$avp(rtcp)+"\"}, + {\"Flow-Usage\": 0}]}, + {\"Media-Type\": 0}, + {\"Max-Requested-Bandwidth-DL\": 41000}, + {\"Max-Requested-Bandwidth-UL\": 41000}, + {\"Codec-Data\": \"uplink\noffer\n"+$avp(stream)+"\"}, + {\"Codec-Data\": \"downlink\nanswer\n"+$(rb{sdp.stream,0})+"\"}, + {\"Flow-Status\": 2}]"; + $dlg_val(session_id) = $var(session_id); + break; + } + $var(payload) = "[ + { \"Session-Id\": \""+$var(session_id)+"\" }, + { \"Auth-Application-Id\": 16777236 }, + { \"Origin-Host\": \"pcscf.IMS_DOMAIN\" }, + { \"Origin-Realm\": \"IMS_DOMAIN\" }, + { \"Destination-Realm\": \"EPC_DOMAIN\" }, + { \"Vendor-Specific-Application-Id\": [{\"Vendor-Id\": 10415}, + {\"Auth-Application-Id\": 16777236}]}, + { \"AF-Application-Identifier\": \"IMS Services\" }, + { \"Authorization-Lifetime\": 3600 }, + { \"Subscription-ID\": [{\"Subscription-Id-Type\": 2}, + {\"Subscription-Id-Data\": \""+$fu+"\"}]}, + { \"Reservation-Priority\": 0 }, + { \"Media-Component-Description\": "+$var(media_component)+"}, + { \"Frame-IP-Address\": \""+$avp(si)+"\" }, + { \"Specific-Action\": 1 }, + { \"Specific-Action\": 2 }, + { \"Specific-Action\": 3 }, + { \"Specific-Action\": 4 }, + { \"Specific-Action\": 5 }, + { \"Specific-Action\": 6 }, + { \"Specific-Action\": 12 }, + { \"Auth-Grace-Period\": 0 }, + { \"Session-Timeout\": 3600 } + ]"; + + $var(rc) = dm_send_request(16777236, 265, $var(payload), $var(rpl_avps)); + xlog("[$ci] AAA rc: $var(rc), AAA AVPs: $var(rpl_avps)\n"); +} + +route[session_termination] { + if ($si != "SCSCF_IP") + rtpengine_delete(); + + xlog("L_INFO","[$ci] Received BYE from $si for $tu - doing STR\n"); + + $var(payload) = "[ + { \"Session-Id\": \""+$dlg_val(session_id)+"\" }, + { \"Auth-Application-Id\": 16777236 }, + { \"Origin-Host\": \"pcscf.IMS_DOMAIN\" }, + { \"Origin-Realm\": \"IMS_DOMAIN\" }, + { \"Destination-Realm\": \"EPC_DOMAIN\" }, + { \"Vendor-Specific-Application-Id\": [{\"Vendor-Id\": 10415}, + {\"Auth-Application-Id\": 16777236}]}, + { \"AF-Application-Identifier\": \"IMS Services\" }, + { \"Termination-Cause\": 1 } + ]"; + + $var(rc) = dm_send_request(16777236, 275, $var(payload), $var(rpl_avps)); + xlog("[$ci] STA rc: $var(rc), STA AVPs: $var(rpl_avps)\n"); +} + +route[extract_ip_port] { + $var(ip) = $(rb{sdp.line,c}{s.select,2, }); + $var(port) = $(rb{sdp.line,m}{s.select,1, }); + $var(rtcp) = $(var(port){s.int}) + 1; +} + +event_route[E_DM_REQUEST] { + if ($param(app_id) == 16777236 && $param(cmd_code) == 274) { + $var(ip) = $(param(sess_id){s.select,0,;}); + $var(port) = $(param(sess_id){s.select,1,;}{s.int}); + xlog("[diameter] removing $var(ip):$var(port) contact\n"); + remove_ip_port($var(ip), $var(port), "location"); + $var(payload) = "[ + { \"Vendor-Specific-Application-Id\": [{\"Vendor-Id\": 10415}, + {\"Auth-Application-Id\": 16777236}]}, + { \"Result-Code\": 2001 }, + { \"Auth-Session-State\": 0 }, + { \"Origin-Host\": \"pcscf.IMS_DOMAIN\" }, + { \"Origin-Realm\": \"IMS_DOMAIN\" } + ]"; + dm_send_answer($var(payload)); + + } +} + +route[handle_presence] { + if (!t_newtran()){ + sl_reply_error(); + exit; + } + if ($hdr(Event) != "reg") { + xlog("L_ERR", "[$ci] Unhandled event $hdr(Event)\n"); + send_reply(489, "Bad Event"); + exit; + } + + if (is_method("PUBLISH")) + handle_publish(); + if (is_method("SUBSCRIBE")) + handle_subscribe(); +} diff --git a/opensips_ims_pcscf/opensips_vonr.cfg b/opensips_ims_pcscf/opensips_vonr.cfg new file mode 100644 index 0000000..7dcf035 --- /dev/null +++ b/opensips_ims_pcscf/opensips_vonr.cfg @@ -0,0 +1,494 @@ +# +# OpenSIPS residential configuration script +# by OpenSIPS Solutions +# +# This script was generated via "make menuconfig", from +# the "Residential" scenario. +# You can enable / disable more features / functionalities by +# re-generating the scenario with different options.# +# +# Please refer to the Core CookBook at: +# https://opensips.org/Resources/DocsCookbooks +# for a explanation of possible statements, functions and parameters. +# + + +####### Global Parameters ######### + +/* uncomment the following lines to enable debugging */ +#debug_mode=yes + +log_level=3 +xlog_level=3 +#mem_log=6 +log_stderror=yes +log_stdout=yes +log_facility=LOG_LOCAL0 + +udp_workers=4 + +/* uncomment the next line to enable the auto temporary blacklisting of + not available destinations (default disabled) */ +#disable_dns_blacklist=no + +/* uncomment the next line to enable IPv6 lookup after IPv4 dns + lookup failures (default disabled) */ +#dns_try_ipv6=yes + +dns=no + +socket=udp:PCSCF_IP:5060 +socket=tcp:PCSCF_IP:5060 +socket=ipsec:PCSCF_IP:6100,5100 + +alias="pcscf.IMS_DOMAIN" + + +#set module path +mpath="/usr/local/opensips/modules" + +####### Modules Section ######## + +#### MYSQL module +loadmodule "db_mysql.so" + +#### SIGNALING module +loadmodule "signaling.so" + +#### StateLess module +loadmodule "sl.so" + +#### Transaction Module +loadmodule "tm.so" +modparam("tm", "fr_timeout", 5) +modparam("tm", "fr_inv_timeout", 30) +modparam("tm", "restart_fr_on_each_reply", 0) +modparam("tm", "onreply_avp_mode", 1) + +#### Record Route Module +loadmodule "rr.so" +/* do not append from tag to the RR (no need for this script) */ +modparam("rr", "append_fromtag", 0) + +#### MAX ForWarD module +loadmodule "maxfwd.so" + +#### NATHELPER module +loadmodule "nathelper.so" + +#### SIP MSG OPerationS module +loadmodule "sipmsgops.so" + +#### FIFO Management Interface +loadmodule "mi_fifo.so" +modparam("mi_fifo", "fifo_name", "/var/run/opensips/opensips_fifo") +modparam("mi_fifo", "fifo_mode", 0666) + +#### USeR LOCation module +loadmodule "usrloc.so" +modparam("usrloc", "nat_bflag", "NAT") +modparam("usrloc", "mi_dump_kv_store", 1) +modparam("usrloc", "working_mode_preset", "single-instance-no-db") + +#### REGISTRAR module +loadmodule "registrar.so" +modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT") +/* uncomment the next line not to allow more than 10 contacts per AOR */ +#modparam("registrar", "max_contacts", 10) + +#### ACCounting module +loadmodule "acc.so" +/* what special events should be accounted ? */ +modparam("acc", "early_media", 0) +modparam("acc", "report_cancels", 0) +/* by default we do not adjust the direct of the sequential requests. + if you enable this parameter, be sure to enable "append_fromtag" + in "rr" module */ +modparam("acc", "detect_direction", 0) + +#### proto_udp module +loadmodule "dispatcher.so" + +loadmodule "proto_udp.so" +loadmodule "proto_tcp.so" +loadmodule "proto_ipsec.so" +loadmodule "dialog.so" + +#### dbtext module +loadmodule "db_text.so" +modparam("dispatcher", "db_url", "text:///etc/opensips/db") + +modparam("proto_ipsec", "min_spi", 10000) +modparam("proto_ipsec", "max_spi", 10100) +modparam("proto_ipsec", "allowed_algorithms", "hmac-sha-1-96=null, hmac-md5-96=null") + +#### RTPENGINE module +loadmodule "rtpengine.so" +modparam("rtpengine", "rtpengine_sock", "udp:RTPENGINE_IP:2223") + + +loadmodule "event_route.so" +loadmodule "json.so" + +#### PRESENCE modules +loadmodule "presence.so" +loadmodule "presence_reginfo.so" +loadmodule "pua.so" +modparam("pua|presence","db_url", "mysql://opensips_pcscf:heslo@MYSQL_IP/opensips_pcscf") + +loadmodule "pua_reginfo.so" + +modparam("pua_reginfo", "ul_domain", "location") +modparam("pua_reginfo", "ul_identities_key", "identities") +modparam("pua_reginfo", "default_domain", "IMS_DOMAIN") +modparam("pua_reginfo", "server_address", "sip:reginfo@pcscf.IMS_DOMAIN") + + +##### N5 HTTP2 Modules and setting + +loadmodule "rest_client.so" +modparam("rest_client", "curl_timeout", 7) +modparam("rest_client", "connection_timeout", 4) +modparam("rest_client", "curl_http_version", 5) + +####### Routing Logic ######## + +# main request routing logic + +route{ + xlog("L_INFO", "[$ci] Start route time [$Tf] method ($rm) r-uri ($ru) \n"); + set_via_handling("force-rport"); + + if (!mf_process_maxfwd_header(10)) { + send_reply(483,"Too Many Hops"); + exit; + } + + if (has_totag()) { + + # handle hop-by-hop ACK (no routing required) + if ( is_method("ACK") && t_check_trans() ) { + t_relay(); + exit; + } + + # sequential request within a dialog should + # take the path determined by record-routing + if ( !loose_route() ) { + # we do record-routing for all our traffic, so we should not + # receive any sequential requests without Route hdr. + send_reply(404,"Not here"); + exit; + } + + if (is_method("BYE")) { + # do accounting even if the transaction fails + do_accounting("log","failed"); + route(session_termination); + } + + if (is_method("UPDATE")) { + if ($si != "SCSCF_IP") + rtpengine_offer("replace-origin"); + else + t_on_reply("rtpengine_answer"); + } + + if (is_method("SUBSCRIBE|NOTIFY") && is_myself($rd)) { + route(handle_presence); + exit; + } + + # route it out to whatever destination was set by loose_route() + # in $du (destination URI). + route(relay); + exit; + } + + # CANCEL processing + if (is_method("CANCEL")) { + if (t_check_trans()) + t_relay(); + exit; + } + + # absorb retransmissions, but do not create transaction + t_check_trans(); + + if (is_method("REGISTER")) { + xlog("L_INFO", "[$ci] Received REGISTER for $tu - relaying to I-CSCF\n"); + append_hf("Path: \r\n"); + + if ($hdr(Security-Client)) { + setflag("SEC_AGREE"); + append_hf("P-Visited-Network-ID: IMS_DOMAIN\r\n"); + } + t_on_reply("register_reply"); + route(relay); + exit; + } else if (is_method("SUBSCRIBE|PUBLISH")) { + xlog("L_INFO", "[$ci] Received $rm for $tu - handling\n"); + route(handle_presence); + exit; + } else if (is_method("INVITE")) { + if (loose_route()) { + xlog("L_INFO", "[$ci] Received INVITE for $tu - relaying to S-CSCF ($ru/$du)\n"); + remove_hf("Security-Verify"); + if (list_hdr_has_option("Require", "sec-agree")) + list_hdr_remove_option("Require", "sec-agree"); + if (list_hdr_has_option("Proxy-Require", "sec-agree")) + list_hdr_remove_option("Proxy-Require", "sec-agree"); + append_hf("P-Visited-Network-ID: IMS_DOMAIN\r\n"); + $socket_out = "tcp:PCSCF_IP:5060"; + $avp(si) = $si; + $avp(sub_id) = "imsi-" + $fU; + rtpengine_offer("replace-origin"); + } else { + xlog("L_INFO", "[$ci] Received INVITE for $tu - looking up from S-CSCF ($ru/$du/$tu)\n"); + $rU = $(tU{s.select,0,;}); + $avp(sub_id) = "imsi-" + $tU; + if (!lookup("location")) { + xlog("L_ERR", "[$ci] user $rU not found\n"); + t_reply(404, "Not here"); + exit; + } + } + route(extract_ip_port); + $avp(ip) = $var(ip); + $avp(port) = $var(port); + $avp(rtcp) = $var(rtcp); + $avp(stream) = $(rb{sdp.stream,0}); + t_on_reply("invite_reply"); + if (!record_route()) { + xlog("L_ERR", "[$ci] Cannot do record_route()\n"); + t_reply(503, "Internal Error"); + exit; + } + if (!create_dialog()) { + xlog("L_ERR", "[$ci] Cannot create_dialog()\n"); + t_reply(503, "Internal Error"); + exit; + } + + if (!t_relay()) { + xlog("L_ERR", "[$ci] Cannot relay to $ru/$du\n"); + t_reply(503, "Internal Error"); + exit; + } + exit; + } + + send_reply(405,"Method Not Allowed"); + exit; +} + + +route[relay] { + if (!t_relay()) { + send_reply(500,"Internal Error"); + } + exit; +} + +onreply_route[register_reply] { + xlog("L_INFO","[$ci] Received REGISTER reply $rs from $si for $tu\n"); + if ($T_reply_code == 401) { + if (!isflagset("SEC_AGREE") || ipsec_create()) + route(dm_send_aar, "control"); + } else if ($T_reply_code == 200) { + for ($var(item) in $(hdr(P-Associated-URI)[*])) { + $var(uri_len) = $(var(item){s.len}) - 2; + $var(uri) = $(var(item){s.substr, 1, $var(uri_len)}); + if (!save("location", "no-reply, path-off", $var(uri))) { + xlog("L_ERR", "[$ci] could not save aor [$var(uri)]\n"); + } else { + ul_add_key("location", "$tU@$td", "identities", "$var(uri)"); + } + } + reginfo_update("$tU@$td"); + } +} + +onreply_route[invite_reply] { + + if (!has_body_part("application/sdp")) { + xlog("L_INFO","[$ci] Received INVITE reply $rs from $si for $tu - without SDP\n"); + return; + } else if (isflagset("INVITE_AAA")) { + xlog("L_INFO","[$ci] Received INVITE reply $rs from $si for $tu - AAA done\n"); + return; + } + xlog("L_INFO","[$ci] Received INVITE reply $rs from $si for $tu - doing AAR\n"); + route(extract_ip_port); + if ($avp(si) == NULL) { + rtpengine_answer("replace-origin"); + $avp(si) = $si; + $var(tmp_ip) = $avp(ip); + $var(tmp_port) = $avp(port); + $avp(ip) := $var(ip); + $avp(port) := $var(port); + $var(ip) = $var(tmp_ip); + $var(port) = $var(tmp_port); + } + route(dm_send_aar, "audio"); + setflag("INVITE_AAA"); +} + +onreply_route[rtpengine_answer] { + if (!has_body_part("application/sdp")) + return; + rtpengine_answer("replace-origin"); +} + + +route[dm_send_aar] { + + switch ($param(1)) { + + case "control": + if ($ipsec(ip) != NULL) { + $var(src_ip) = $ipsec_ue(ip); + $var(src_port) = $ipsec_ue(port-c); + $var(dst_ip) = $ipsec(ip); + $var(dst_port) = $ipsec(port-s); + $var(sess_port) = $ipsec_ue(port-s); + } else { + $var(src_ip) = $si; + $var(src_port) = $sp; + $var(dst_ip) = $socket_in(ip); + $var(dst_port) = $socket_in(port); + $var(sess_port) = $sp; + } + + $var(afAppId) = "+g.3gpp.icsi-ref=\\\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel\\\""; + $var(dnn) = "ims"; + $json(array1) := "[\"permit in ip from "+$var(src_ip)+" "+$var(src_port)+" to "+$var(dst_ip)+" "+$var(dst_port)+"\", \"permit out ip from "+$var(dst_ip)+" "+$var(dst_port)+" to "+$var(src_ip)+" "+$var(src_port)+"\"]"; + $var(events) = "[{\"event\": \"QOS_NOTIF\", \"notifMethod\": \"PERIODIC\"}, {\"event\": \"ANI_REPORT\", \"notifMethod\": \"ONE_TIME\"}]"; + $var(notifUri) = "http://N5_BIND_IP:N5_BIND_PORT"; + $var(sponStatus) = "SPONSOR_DISABLED"; + $var(supi) = "imsi-"+ $au; + $var(suppFeat) = "2"; + $var(ueIpv4) = $var(src_ip); + + $json(nf_reg_body) = "{ + \"ascReqData\":{ + \"afAppId\": \""+$var(afAppId)+"\", + \"dnn\": \""+$var(dnn)+"\" , + \"medComponents\":{ + \"0\":{ + \"medCompN\":0, + \"qosReference\":\"qosVoNR\", + \"medType\":\"CONTROL\", + \"medSubComps\":{ + \"0\":{ + \"fNum\":0, + \"fDescs\": "+$json(array1)+", + \"fStatus\":\"ENABLED\", + \"flowUsage\":\"AF_SIGNALLING\" + } + } + } + }, + \"evSubsc\":{ \"events\": "+$var(events)+"}, + \"notifUri\": \""+$var(notifUri)+"\" , + \"sponStatus\": \""+$var(sponStatus)+"\", + \"supi\": \""+$var(supi)+"\", + \"suppFeat\": \""+$var(suppFeat)+"\", + \"ueIpv4\": \""+$var(ueIpv4)+"\" + } + }"; + rest_post("http://172.22.0.27:7777/npcf-policyauthorization/v1/app-sessions", "$json_pretty(nf_reg_body)", "application/json" , $var(resp), $var(ct), $var(rcode)); + xlog("L_INFO", "N5 Response: [$(hdr(location)) ] \n"); + xlog("L_INFO", "N5 Response: [$var(resp)] \n"); + xlog("L_INFO", "N5 Response: [$var(ct)] \n"); + xlog("L_INFO", "N5 Response: [$var(rcode)] \n"); + break; + + case "audio": + $var(afAppId) = "+g.3gpp.icsi-ref=\\\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel\\\""; + $var(dnn) = "ims"; + + $json(array1) := "[\"permit in ip from "+$avp(ip)+" "+$avp(port)+" to "+$var(ip)+" "+$var(port)+"\", \"permit out ip from "+$var(ip)+" "+$var(port)+" to "+$avp(ip)+" "+$avp(port)+"\"]"; + $json(array2) := "[\"permit in ip from "+$avp(ip)+" "+$avp(rtcp)+" to "+$var(ip)+" "+$var(rtcp)+"\", \"permit out ip from "+$var(ip)+" "+$var(rtcp)+" to "+$avp(ip)+" "+$avp(rtcp)+"\"]"; + + $var(events) = "[{\"event\": \"QOS_NOTIF\", \"notifMethod\": \"PERIODIC\"}, {\"event\": \"ANI_REPORT\", \"notifMethod\": \"ONE_TIME\"}]"; + $var(notifUri) = "http://N5_BIND_IP:N5_BIND_PORT"; + $var(sponStatus) = "SPONSOR_DISABLED"; + $var(supi) = $avp(sub_id); + $var(suppFeat) = "2"; + $var(ueIpv4) = $avp(ip); + + $json(nf_call_body) = "{ + \"ascReqData\": { + \"afAppId\": \""+$var(afAppId)+"\", + \"dnn\": \""+$var(dnn)+"\" , + \"medComponents\":{ + \"0\":{ + \"medCompN\":0, + \"qosReference\":\"qosVoNR\", + \"medType\":\"AUDIO\", + \"medSubComps\":{ + \"0\":{ + \"fNum\":1, + \"fDescs\": "+$json(array1)+", + \"fStatus\":\"ENABLED\", + \"marBwDl\":\"5000 Kbps\", + \"marBwUl\":\"3000 Kbps\", + \"flowUsage\":\"NO_INFO\" + }, + \"1\":{ + \"fNum\":2, + \"fDescs\": "+$json(array2)+", + \"fStatus\":\"ENABLED\", + \"marBwDl\":\"5000 Kbps\", + \"marBwUl\":\"3000 Kbps\", + \"flowUsage\":\"RTCP\" + } + } + } + }, + \"evSubsc\":{ \"events\": "+$var(events)+"}, + \"notifUri\": \""+$var(notifUri)+"\" , + \"sponStatus\": \""+$var(sponStatus)+"\", + \"supi\": \""+$var(supi)+"\", + \"suppFeat\": \""+$var(suppFeat)+"\", + \"ueIpv4\": \""+$var(ueIpv4)+"\" + } + }"; + rest_post("http://172.22.0.27:7777/npcf-policyauthorization/v1/app-sessions", "$json_pretty(nf_call_body)", "application/json" , $var(resp), $var(ct), $var(rcode)); + xlog("L_INFO", "N5 Response: [$(hdr(location)) ] \n"); + xlog("L_INFO", "N5 Response: [$var(resp)] \n"); + xlog("L_INFO", "N5 Response: [$var(ct)] \n"); + xlog("L_INFO", "N5 Response: [$var(rcode)] \n"); + break; + } +} +route[session_termination] { + if ($si != "SCSCF_IP") + rtpengine_delete(); + xlog("L_INFO","[$ci] Received BYE from $si for $tu - can't terminate N5: WIP N5 Termination logic\n"); +} + +route[extract_ip_port] { + $var(ip) = $(rb{sdp.line,c}{s.select,2, }); + $var(port) = $(rb{sdp.line,m}{s.select,1, }); + $var(rtcp) = $(var(port){s.int}) + 1; +} + + +route[handle_presence] { + if (!t_newtran()){ + sl_reply_error(); + exit; + } + if ($hdr(Event) != "reg") { + xlog("L_ERR", "[$ci] Unhandled event $hdr(Event)\n"); + send_reply(489, "Bad Event"); + exit; + } + + if (is_method("PUBLISH")) + handle_publish(); + if (is_method("SUBSCRIBE")) + handle_subscribe(); +} diff --git a/opensips_ims_pcscf/pcscf.dictionary b/opensips_ims_pcscf/pcscf.dictionary new file mode 100644 index 0000000..f6406d5 --- /dev/null +++ b/opensips_ims_pcscf/pcscf.dictionary @@ -0,0 +1,78 @@ +VENDOR 10415 TGPP +VENDOR 13019 ETSI + +ATTRIBUTE Abort-Cause 500 unsigned32 10415 +ATTRIBUTE AF-Application-Identifier 504 string 10415 +ATTRIBUTE Flow-Description 507 string 10415 +ATTRIBUTE Flow-Number 509 unsigned32 10415 +ATTRIBUTE Flow-Status 511 unsigned32 10415 +ATTRIBUTE Flow-Usage 512 unsigned32 10415 +ATTRIBUTE Specific-Action 513 unsigned32 10415 +ATTRIBUTE Max-Requested-Bandwidth-DL 515 unsigned32 10415 +ATTRIBUTE Max-Requested-Bandwidth-UL 516 unsigned32 10415 +ATTRIBUTE Media-Component-Number 518 unsigned32 10415 +ATTRIBUTE Media-Type 520 unsigned32 10415 +ATTRIBUTE Codec-Data 524 string 10415 +ATTRIBUTE Media-Sub-Component 519 grouped 10415 +{ + Flow-Number | REQUIRED | 1 + Flow-Usage | REQUIRED | 1 + Flow-Description | REQUIRED | 9 +} + +ATTRIBUTE Media-Component-Description 517 grouped 10415 +{ + Media-Component-Number | REQUIRED | 1 + Media-Sub-Component | REQUIRED | 1 + Media-Type | REQUIRED | 1 + Max-Requested-Bandwidth-DL | REQUIRED | 1 + Max-Requested-Bandwidth-UL | REQUIRED | 1 + Flow-Status | REQUIRED | 1 +} +ATTRIBUTE IP-CAN-Type 1027 unsigned32 10415 +ATTRIBUTE RAT-Type 1032 unsigned32 10415 + +ATTRIBUTE Subscription-Id-Type 450 unsigned32 +ATTRIBUTE Subscription-Id-Data 444 string +ATTRIBUTE Subscription-ID 443 grouped +{ + Subscription-Id-Type | REQUIRED | 1 + Subscription-Id-Data | REQUIRED | 1 +} +ATTRIBUTE Frame-IP-Address 8 ip +ATTRIBUTE Reservation-Priority 458 unsigned32 13019 + +APPLICATION-AUTH 16777236/10415 3GPP Rx + +REQUEST 265 AA Request +{ + Session-Id | REQUIRED | 1 + Auth-Application-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Realm | REQUIRED | 1 + AF-Application-Identifier | REQUIRED | 1 + Authorization-Lifetime | REQUIRED | 1 + Subscription-ID | REQUIRED | 1 + Specific-Action | REQUIRED | 9 + Frame-IP-Address | REQUIRED | 1 + Reservation-Priority | REQUIRED | 1 + Session-Timeout | OPTIONAL | 1 + Auth-Grace-Period | OPTIONAL | 1 +} +# Vendor-Specific-Application-Id | REQUIRED | 1 +# Media-Component-Description | REQUIRED | 1 + +ANSWER 265 AA Answer +{ + Session-Id | REQUIRED | 1 + Auth-Application-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Host | OPTIONAL | 1 + Destination-Realm | OPTIONAL | 1 + Result-Code | OPTIONAL | 1 + Experimental-Result | OPTIONAL | 1 + IP-CAN-Type | OPTIONAL | 1 + RAT-Type | OPTIONAL | 1 +} diff --git a/opensips_ims_pcscf/pcscf_init.sh b/opensips_ims_pcscf/pcscf_init.sh new file mode 100755 index 0000000..185db44 --- /dev/null +++ b/opensips_ims_pcscf/pcscf_init.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +sh -c "echo 1 > /proc/sys/net/ipv4/ip_nonlocal_bind" +sh -c "echo 1 > /proc/sys/net/ipv6/ip_nonlocal_bind" + +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +mkdir -p /etc/opensips +cp /mnt/pcscf/freeDiameter.conf /etc/opensips +cp /mnt/pcscf/pcscf.dictionary /etc/opensips +cp /mnt/pcscf/opensips.cfg /etc/opensips +cp -r /mnt/pcscf/db /etc/opensips + +# For mi_fifo module. +mkdir -p /var/run/opensips + +if [[ ${DEPLOY_MODE} == 5G ]]; +then + cp /mnt/pcscf/opensips_vonr.cfg /etc/opensips/opensips.cfg +fi + +while ! mysqladmin ping -h ${MYSQL_IP} --silent; do + sleep 5; +done + +# Sleep until permissions are set +sleep 10; + +# Create PCSCF database, populate tables and grant privileges +if [[ -z "`mysql -u root -h ${MYSQL_IP} -qfsBe "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='opensips_pcscf'" 2>&1`" ]]; +then + mysql -u root -h ${MYSQL_IP} -e "create database opensips_pcscf;" + mysql -u root -h ${MYSQL_IP} opensips_pcscf < /usr/local/share/opensips/mysql/standard-create.sql + mysql -u root -h ${MYSQL_IP} opensips_pcscf < /usr/local/share/opensips/mysql/presence-create.sql + PCSCF_USER_EXISTS=`mysql -u root -h ${MYSQL_IP} -s -N -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE User = 'opensips_pcscf' AND Host = '%')"` + if [[ "$PCSCF_USER_EXISTS" == 0 ]] + then + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'opensips_pcscf'@'%' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'opensips_pcscf'@'$PCSCF_IP' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON opensips_pcscf.* TO 'opensips_pcscf'@'%'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON opensips_pcscf.* TO 'opensips_pcscf'@'$PCSCF_IP'"; + mysql -u root -h ${MYSQL_IP} -e "FLUSH PRIVILEGES;" + fi +fi + + +sed -i 's|PCSCF_IP|'$PCSCF_IP'|g' /etc/opensips/opensips.cfg +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/opensips/opensips.cfg +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/opensips/opensips.cfg +sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' /etc/opensips/opensips.cfg +sed -i 's|RTPENGINE_IP|'$RTPENGINE_IP'|g' /etc/opensips/opensips.cfg +sed -i 's|MYSQL_IP|'$MYSQL_IP'|g' /etc/opensips/opensips.cfg + +sed -i 's|PCRF_BIND_PORT|'$PCRF_BIND_PORT'|g' /etc/opensips/freeDiameter.conf +sed -i 's|PCSCF_BIND_PORT|'$PCSCF_BIND_PORT'|g' /etc/opensips/freeDiameter.conf +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/opensips/freeDiameter.conf +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/opensips/freeDiameter.conf +sed -i 's|PCRF_IP|'$PCRF_IP'|g' /etc/opensips/freeDiameter.conf +sed -i 's|PCSCF_IP|'$PCSCF_IP'|g' /etc/opensips/freeDiameter.conf + +# Add static route to route traffic back to UE as there is not NATing +ip r add ${UE_IPV4_IMS} via ${UPF_IP} + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +exec opensips -f /etc/opensips/opensips.cfg -F $@ diff --git a/opensips_ims_scscf/freeDiameter.conf b/opensips_ims_scscf/freeDiameter.conf new file mode 100644 index 0000000..fbeae7f --- /dev/null +++ b/opensips_ims_scscf/freeDiameter.conf @@ -0,0 +1,13 @@ +Identity = "scscf.IMS_DOMAIN"; +Realm = "IMS_DOMAIN"; +Port = SCSCF_BIND_PORT; +ListenOn = "SCSCF_IP"; +SecPort = 0; +No_SCTP; +NoRelay; + +ConnectPeer = "hss.IMS_DOMAIN" { + No_TLS; + ConnectTo = "PYHSS_IP"; + port = PYHSS_BIND_PORT; +}; diff --git a/opensips_ims_scscf/opensips.cfg b/opensips_ims_scscf/opensips.cfg new file mode 100644 index 0000000..69178b6 --- /dev/null +++ b/opensips_ims_scscf/opensips.cfg @@ -0,0 +1,311 @@ +# +# OpenSIPS residential configuration script +# by OpenSIPS Solutions +# +# This script was generated via "make menuconfig", from +# the "Residential" scenario. +# You can enable / disable more features / functionalities by +# re-generating the scenario with different options.# +# +# Please refer to the Core CookBook at: +# https://opensips.org/Resources/DocsCookbooks +# for a explanation of possible statements, functions and parameters. +# + + +####### Global Parameters ######### + +/* uncomment the following lines to enable debugging */ +#debug_mode=yes + +log_level=3 +xlog_level=3 +log_stderror=yes +log_stdout=yes +xlog_buf_size=16384 +log_facility=LOG_LOCAL0 + +udp_workers=4 + +/* uncomment the next line to enable the auto temporary blacklisting of + not available destinations (default disabled) */ +#disable_dns_blacklist=no + +/* uncomment the next line to enable IPv6 lookup after IPv4 dns + lookup failures (default disabled) */ +#dns_try_ipv6=yes + + +socket=udp:SCSCF_IP:6060 +socket=tcp:SCSCF_IP:6060 + +alias="scscf.IMS_DOMAIN" + +#set module path +mpath="/usr/local/opensips/modules" + +####### Modules Section ######## + +#### MYSQL module +loadmodule "db_mysql.so" + +#### SIGNALING module +loadmodule "signaling.so" + +#### StateLess module +loadmodule "sl.so" + +#### Transaction Module +loadmodule "tm.so" +modparam("tm", "fr_timeout", 5) +modparam("tm", "fr_inv_timeout", 30) +modparam("tm", "restart_fr_on_each_reply", 0) +modparam("tm", "onreply_avp_mode", 1) + +#### Record Route Module +loadmodule "rr.so" +/* do not append from tag to the RR (no need for this script) */ +modparam("rr", "append_fromtag", 0) + +#### MAX ForWarD module +loadmodule "maxfwd.so" + +#### SIP MSG OPerationS module +loadmodule "sipmsgops.so" + +#### FIFO Management Interface +loadmodule "mi_fifo.so" +modparam("mi_fifo", "fifo_name", "/var/run/opensips/opensips_fifo") +modparam("mi_fifo", "fifo_mode", 0666) + +#### USeR LOCation module +loadmodule "usrloc.so" +modparam("usrloc", "nat_bflag", "NAT") +modparam("usrloc", "working_mode_preset", "single-instance-no-db") + +#### REGISTRAR module +loadmodule "registrar.so" +modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT") +modparam("registrar", "attr_avp", "$avp(attr)") +/* uncomment the next line not to allow more than 10 contacts per AOR */ +#modparam("registrar", "max_contacts", 10) + +#### ACCounting module +loadmodule "acc.so" +/* what special events should be accounted ? */ +modparam("acc", "early_media", 0) +modparam("acc", "report_cancels", 0) +/* by default we do not adjust the direct of the sequential requests. + if you enable this parameter, be sure to enable "append_fromtag" + in "rr" module */ +modparam("acc", "detect_direction", 0) + +loadmodule "proto_udp.so" +loadmodule "proto_tcp.so" + +#### aaa_diameter module +loadmodule "aaa_diameter.so" +modparam("aaa_diameter", "fd_log_level", 1) # max amount of logging, quite annoying +modparam("aaa_diameter", "realm", "IMS_DOMAIN") +modparam("aaa_diameter", "peer_identity", "hss") +modparam("aaa_diameter", "aaa_url", + "diameter:/etc/opensips/freeDiameter.conf;extra-avps-file:/etc/opensips/scscf.dictionary") +loadmodule "auth_aka.so" +modparam("auth_aka", "default_av_mgm", "diameter") +modparam("auth_aka", "default_qop", "auth") +loadmodule "aka_av_diameter.so" +modparam("aka_av_diameter", "realm", + "scscf.IMS_DOMAIN") +modparam("aka_av_diameter", "aaa_url", + "diameter:/etc/opensips/freeDiameter.conf;extra-avps-file:/etc/opensips/scscf.dictionary") + +#### dialplan module +loadmodule "dialplan.so" +modparam("dialplan","db_url", "mysql://opensips_scscf:heslo@MYSQL_IP/opensips_scscf") + + +#### auth module +loadmodule "auth.so" + +#### JSON module +loadmodule "json.so" + +#### XML module +loadmodule "xml.so" + + + +####### Routing Logic ######## + +# main request routing logic + +route{ + xlog("L_INFO", "[$ci] Start route time [$Tf] method ($rm) r-uri ($ru) \n"); + + if (!mf_process_maxfwd_header(10)) { + send_reply(483,"Too Many Hops"); + exit; + } + + if (has_totag()) { + + # handle hop-by-hop ACK (no routing required) + if ( is_method("ACK") && t_check_trans() ) { + t_relay(); + exit; + } + + # sequential request within a dialog should + # take the path determined by record-routing + if ( !loose_route() ) { + # we do record-routing for all our traffic, so we should not + # receive any sequential requests without Route hdr. + send_reply(404,"Not here"); + exit; + } + + if (is_method("BYE")) { + # do accounting even if the transaction fails + do_accounting("log","failed"); + } + + # route it out to whatever destination was set by loose_route() + # in $du (destination URI). + route(relay); + exit; + } + + # CANCEL processing + if (is_method("CANCEL")) { + if (t_check_trans()) + t_relay(); + exit; + } + + # absorb retransmissions, but do not create transaction + t_check_trans(); + + if (is_method("REGISTER")) { + xlog("L_INFO", "[$ci] Received REGISTER for $tu - doing authorization\n"); + if (!aka_www_authorize()) { + if (!async(aka_www_challenge(), aka_resume_mar)) + t_reply(500, "Internal Error"); + exit; + } + xlog("L_INFO", "[$ci] Received REGISTER for $tu - authorized, doing SAR\n"); + $var(payload) = "[ + { \"Session-Id\": \"scscf.IMS_DOMAIN;"+$Ts+"."+$Tsm+";"+$pp+"\" }, + { \"Origin-Host\": \"scscf.IMS_DOMAIN\" }, + { \"Origin-Realm\": \"IMS_DOMAIN\" }, + { \"Destination-Realm\": \"IMS_DOMAIN\" }, + { \"Vendor-Specific-Application-Id\": [{\"Vendor-Id\": 10415}, + {\"Auth-Application-Id\": 16777216}]}, + { \"Auth-Session-State\": 1 }, + { \"User-Name\": \""+$fU+"@"+$fd+"\" }, + { \"Public-Identity\": \""+$fu+"\" }, + { \"Server-Assignment-Type\": 1 }, + { \"User-Data-Already-Available\": 0}, + { \"Server-Name\": \"sip:scscf.IMS_DOMAIN:6060\" } + ]"; + + if (!async(dm_send_request(16777216, 301, $var(payload), $var(rpl_avps)), aka_resume_sar)) { + t_reply(500, "Internal Error"); + exit; + } + exit; + } else if (is_method("INVITE")) { + + xlog("L_INFO", "[$ci] Received INVITE for $tu/$ru - checking dialplan\n"); + loose_route(); # consume preloaded routes + if (!record_route()) { + xlog("L_ERR", "[$ci] Cannot do record_route()\n"); + t_reply(503, "Internal Error"); + exit; + } + if ($ru =~ "^tel:") { + $var(tel_user) = $rU; + $var(tel_domain) = $(ru{uri.param,phone-context}); + $ru = "sip:" + $var(tel_user) + "@" + $var(tel_domain); + } else { + $rU = $(rU{s.select,0,;}); + } + if (!dp_translate(1, $rU, $var(dialplan))) { + $var(dialplan) = "USER"; + xlog("L_DBG", "[$ci] unknown dialplan - considering $var(dialplan)\n"); + } + xlog("L_INFO", "[$ci] Dial $rU is a $var(dialplan) dialplan\n"); + switch ($var(dialplan)) { + case "USER": + xlog("L_INFO", "[$ci] lookup user $rU/$(oU{s.select,0,;})\n"); + if (!lookup("location")) { + xlog("L_ERR", "[$ci] Received INVITE for $tu/$ru not registered - sending to service\n"); + t_reply(404, "User not found"); + exit; + } + break; + case "SERVICE": + # TODO: handle service + case "APPLICATION": + # TODO: handle application server + default: + xlog("L_ERR", "[$ci] unknown $var(dialplan) dialplan\n"); + t_reply(503, "Unknown dialplan"); + exit; + } + if (!t_relay()) { + xlog("L_ERR", "[$ci] Cannot relay to $ru\n"); + t_reply(503, "Internal Error"); + } + exit; + } + + send_reply(503,"Not Implemented"); + exit; +} + + +route[relay] { + if (!t_relay()) { + send_reply(500,"Internal Error"); + } + exit; +} + +route[aka_resume_mar] { + xlog("L_DBG", "[$ci] MAA rc: $rc\n"); +} + +route[aka_resume_sar] { + xlog("[$ci] SAA rc: $var(rc), SAA AVPs: $var(rpl_avps)\n"); + $avp(attr) = $ct.fields(params); + append_to_reply("Service-Route: \r\n"); + $json(rpl_avps) := $var(rpl_avps); + for ($var(item) in $(json(rpl_avps)[*])) { + $json(item) := $var(item); + for ($var(key) in $(json(item.keys)[*])) { + if ($var(key) == "Cx-User-Data") { + $xml(data) := $json(item/$var(key)); + $xml(profile) := $xml(data/IMSSubscription/ServiceProfile); + $var(idx) = 0; + while ($xml(profile/ServiceProfile/PublicIdentity[$var(idx)]) != NULL) { + append_to_reply("P-Associated-URI: <$xml(profile/ServiceProfile/PublicIdentity[$var(idx)]/Identity.val)>\r\n"); + $var(uri) = $xml(profile/ServiceProfile/PublicIdentity[$var(idx)]/Identity.val); + if ($var(uri) == $tu) { + # Save AoR for IMPU in format sip:IMSI@IMS_DOMAIN and send 200 response. + if (!save("location", "path-lazy")) { + t_reply(503, "Internal Error"); + exit; + } + } else { + # Save AoR for IMPU in other formats and dont send response. + if (!save("location", "no-reply, path-lazy", $var(uri))) { + t_reply(503, "Internal Error"); + exit; + } + } + $var(idx) = $var(idx) + 1; + } + } + } + } +} diff --git a/opensips_ims_scscf/scscf.dictionary b/opensips_ims_scscf/scscf.dictionary new file mode 100644 index 0000000..8ae2a37 --- /dev/null +++ b/opensips_ims_scscf/scscf.dictionary @@ -0,0 +1,105 @@ +VENDOR 10415 TGPP + +ATTRIBUTE Visited-Network-Identifier 600 string 10415 +ATTRIBUTE Public-Identity 601 string 10415 +ATTRIBUTE Server-Name 602 string 10415 +ATTRIBUTE Mandatory-Capability 604 unsigned32 10415 +ATTRIBUTE Optional-Capability 605 unsigned32 10415 +ATTRIBUTE Cx-User-Data 606 string 10415 +ATTRIBUTE 3GPP-SIP-Number-Auth-Items 607 unsigned32 10415 +ATTRIBUTE 3GPP-SIP-Authentication-Scheme 608 utf8string 10415 +ATTRIBUTE 3GPP-SIP-Authenticate 609 hexstring 10415 +ATTRIBUTE 3GPP-SIP-Authorization 610 hexstring 10415 +ATTRIBUTE 3GPP-SIP-Authentication-Context 611 string 10415 +ATTRIBUTE 3GPP-SIP-Item-Number 613 unsigned32 10415 +ATTRIBUTE Server-Assignment-Type 614 unsigned32 10415 +ATTRIBUTE User-Data-Already-Available 624 unsigned32 10415 +ATTRIBUTE Confidentiality-Key 625 hexstring 10415 +ATTRIBUTE Integrity-Key 626 hexstring 10415 + +ATTRIBUTE Primary-Event-Charging-Function-Name 619 string 10415 +ATTRIBUTE Secondary-Event-Charging-Function-Name 620 string 10415 +ATTRIBUTE Primary-Charging-Collection-Function-Name 621 string 10415 +ATTRIBUTE Secondary-Charging-Collection-Function-Name 622 string 10415 + +ATTRIBUTE 3GPP-SIP-Auth-Data-Item 612 grouped 10415 +{ + 3GPP-SIP-Item-Number | OPTIONAL | 1 + 3GPP-SIP-Authentication-Scheme | OPTIONAL | 1 + 3GPP-SIP-Authenticate | OPTIONAL | 1 + 3GPP-SIP-Authorization | OPTIONAL | 1 + 3GPP-SIP-Authentication-Context | OPTIONAL | 1 + Confidentiality-Key | OPTIONAL | 1 + Integrity-Key | OPTIONAL | 1 +} + +ATTRIBUTE Charging-Information 618 grouped 10415 +{ + Primary-Event-Charging-Function-Name | OPTIONAL | 1 + Secondary-Event-Charging-Function-Name | OPTIONAL | 1 + Primary-Charging-Collection-Function-Name | OPTIONAL | 1 + Secondary-Charging-Collection-Function-Name | OPTIONAL | 1 +} + + +APPLICATION-AUTH 16777216/10415 3GPP Cx + +REQUEST 301 Server-Assignment Request +{ + Session-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Realm | REQUIRED | 1 + Vendor-Specific-Application-Id | REQUIRED | 1 + Auth-Session-State | REQUIRED | 1 + Public-Identity | REQUIRED | 1 + Server-Name | REQUIRED | 1 + User-Name | REQUIRED | 1 + Server-Assignment-Type | REQUIRED | 1 + User-Data-Already-Available | REQUIRED | 1 +} + +ANSWER 301 Server-Assignment Answer +{ + Session-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Host | OPTIONAL | 1 + Destination-Realm | OPTIONAL | 1 + Vendor-Specific-Application-Id | REQUIRED | 1 + Auth-Session-State | REQUIRED | 1 + User-Name | REQUIRED | 1 + Cx-User-Data | REQUIRED | 1 + Charging-Information | OPTIONAL | 1 + Result-Code | REQUIRED | 1 +} + +REQUEST 303 Multimedia-Auth Request +{ + Session-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Realm | REQUIRED | 1 + Vendor-Specific-Application-Id | REQUIRED | 1 + Auth-Session-State | REQUIRED | 1 + Public-Identity | REQUIRED | 1 + 3GPP-SIP-Number-Auth-Items | REQUIRED | 1 + 3GPP-SIP-Auth-Data-Item | REQUIRED | 1 + Server-Name | REQUIRED | 1 +} + +ANSWER 303 Multimedia-Auth Answer +{ + Session-Id | REQUIRED | 1 + Origin-Host | REQUIRED | 1 + Origin-Realm | REQUIRED | 1 + Destination-Host | OPTIONAL | 1 + Destination-Realm | OPTIONAL | 1 + Vendor-Specific-Application-Id | REQUIRED | 1 + Auth-Session-State | REQUIRED | 1 + Public-Identity | REQUIRED | 1 + 3GPP-SIP-Number-Auth-Items | REQUIRED | 1 + 3GPP-SIP-Auth-Data-Item | REQUIRED | 1 + User-Name | REQUIRED | 1 + Result-Code | REQUIRED | 1 +} diff --git a/opensips_ims_scscf/scscf_init.sh b/opensips_ims_scscf/scscf_init.sh new file mode 100755 index 0000000..d760c58 --- /dev/null +++ b/opensips_ims_scscf/scscf_init.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +mkdir -p /etc/opensips +cp /mnt/scscf/freeDiameter.conf /etc/opensips +cp /mnt/scscf/scscf.dictionary /etc/opensips +cp /mnt/scscf/opensips.cfg /etc/opensips + +# For mi_fifo module. +mkdir -p /var/run/opensips + +while ! mysqladmin ping -h ${MYSQL_IP} --silent; do + sleep 5; +done + +# Sleep until permissions are set +sleep 10; + +# Create SCSCF database, populate tables and grant privileges +if [[ -z "`mysql -u root -h ${MYSQL_IP} -qfsBe "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='opensips_scscf'" 2>&1`" ]]; +then + mysql -u root -h ${MYSQL_IP} -e "create database opensips_scscf;" + mysql -u root -h ${MYSQL_IP} opensips_scscf < /usr/local/share/opensips/mysql/standard-create.sql + mysql -u root -h ${MYSQL_IP} opensips_scscf < /usr/local/share/opensips/mysql/dialplan-create.sql + SCSCF_USER_EXISTS=`mysql -u root -h ${MYSQL_IP} -s -N -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE User = 'opensips_scscf' AND Host = '%')"` + if [[ "$SCSCF_USER_EXISTS" == 0 ]] + then + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'opensips_scscf'@'%' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'opensips_scscf'@'$SCSCF_IP' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON opensips_scscf.* TO 'opensips_scscf'@'%'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON opensips_scscf.* TO 'opensips_scscf'@'$SCSCF_IP'"; + mysql -u root -h ${MYSQL_IP} -e "FLUSH PRIVILEGES;" + fi +fi + +sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' /etc/opensips/freeDiameter.conf +sed -i 's|PYHSS_IP|'$PYHSS_IP'|g' /etc/opensips/freeDiameter.conf +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/opensips/freeDiameter.conf +sed -i 's|PYHSS_BIND_PORT|'$PYHSS_BIND_PORT'|g' /etc/opensips/freeDiameter.conf +sed -i 's|SCSCF_BIND_PORT|'$SCSCF_BIND_PORT'|g' /etc/opensips/freeDiameter.conf + +sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' /etc/opensips/opensips.cfg +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/opensips/opensips.cfg +sed -i 's|MYSQL_IP|'$MYSQL_IP'|g' /etc/opensips/opensips.cfg + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +exec opensips -f /etc/opensips/opensips.cfg -F $@ diff --git a/osmohlr/Dockerfile b/osmohlr/Dockerfile new file mode 100644 index 0000000..eb5700d --- /dev/null +++ b/osmohlr/Dockerfile @@ -0,0 +1,42 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM debian:bookworm + +ENV DEBIAN_FRONTEND=noninteractive +ENV OSMOCOM_REPO="https://downloads.osmocom.org/packages/osmocom:/latest/Debian_12" + +# Install updates and dependencies +RUN apt-get update && \ + apt-get -y install wget gnupg telnet + +RUN wget $OSMOCOM_REPO/Release.key && \ + mv Release.key /etc/apt/trusted.gpg.d/osmocom-latest.asc && \ + echo "deb [signed-by=/etc/apt/trusted.gpg.d/osmocom-latest.asc] $OSMOCOM_REPO/ ./" > /etc/apt/sources.list.d/osmocom-latest.list && \ + apt-get update && apt-get install -f && apt-get --install-suggests -y install osmo-hlr + +CMD /mnt/osmohlr/osmohlr_init.sh && \ + cd /mnt/osmohlr && /usr/bin/osmo-hlr -c /etc/osmocom/osmo-hlr.cfg --db-upgrade diff --git a/osmohlr/osmo-hlr.cfg b/osmohlr/osmo-hlr.cfg new file mode 100644 index 0000000..36681e8 --- /dev/null +++ b/osmohlr/osmo-hlr.cfg @@ -0,0 +1,21 @@ +! +! OsmoHLR example configuration +! +log stderr + logging filter all 1 + logging color 1 + logging print category 1 + logging timestamp 1 + logging print extended-timestamp 1 + logging level linp fatal +! +line vty + no login + bind OSMOHLR_IP +ctrl + bind OSMOHLR_IP +hlr + ! Enable below to auto assign MSISDNs to subscribers + ! subscriber-create-on-demand 5 cs+ps + gsup + bind ip OSMOHLR_IP diff --git a/osmohlr/osmohlr_init.sh b/osmohlr/osmohlr_init.sh new file mode 100755 index 0000000..b66631a --- /dev/null +++ b/osmohlr/osmohlr_init.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +cp /mnt/osmohlr/osmo-hlr.cfg /etc/osmocom + +sed -i 's|OSMOHLR_IP|'$OSMOHLR_IP'|g' /etc/osmocom/osmo-hlr.cfg + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/osmomsc/Dockerfile b/osmomsc/Dockerfile new file mode 100644 index 0000000..ca1087e --- /dev/null +++ b/osmomsc/Dockerfile @@ -0,0 +1,43 @@ +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM debian:bookworm + +ENV DEBIAN_FRONTEND=noninteractive +ENV OSMOCOM_REPO="https://downloads.osmocom.org/packages/osmocom:/latest/Debian_12" + +# Install updates and dependencies +RUN apt-get update && \ + apt-get -y install wget gnupg telnet + +RUN wget $OSMOCOM_REPO/Release.key && \ + mv Release.key /etc/apt/trusted.gpg.d/osmocom-latest.asc && \ + echo "deb [signed-by=/etc/apt/trusted.gpg.d/osmocom-latest.asc] $OSMOCOM_REPO/ ./" > /etc/apt/sources.list.d/osmocom-latest.list && \ + apt-get update && apt-get install -f && apt-get --install-suggests -y install osmo-msc + +CMD /mnt/osmomsc/osmomsc_init.sh && \ + rm -f /mnt/osmomsc/sms.db* && \ + cd /mnt/osmomsc && /usr/bin/osmo-msc -c /etc/osmocom/osmo-msc.cfg diff --git a/osmomsc/osmo-msc.cfg b/osmomsc/osmo-msc.cfg new file mode 100644 index 0000000..23924a3 --- /dev/null +++ b/osmomsc/osmo-msc.cfg @@ -0,0 +1,61 @@ +! +! OsmoMSC configuration saved from vty +! +log stderr + logging filter all 1 + logging color 1 + logging print category 1 + logging timestamp 1 + logging print extended-timestamp 1 + logging level linp fatal +! +line vty + no login + bind OSMOMSC_IP +ctrl + bind OSMOMSC_IP +! +cs7 instance 0 + point-code 0.23.1 +network + network country code MCC + mobile network code MNC + short name OsmoMSC + long name OsmoMSC + encryption a5 0 + rrlp mode none + mm info 1 + mgw 0 +msc + mncc internal + mncc guard-timeout 180 + ncss guard-timeout 30 + assign-tmsi + cs7-instance-a 0 + cs7-instance-iu 0 + auth-tuple-max-reuse-count 3 + auth-tuple-reuse-on-error 1 +mncc-int + default-codec tch-f fr + default-codec tch-h hr +sgs + local-ip OSMOMSC_IP + local-port 29118 + vlr-name vlr.THREEGPP_REALM +hlr + ! IP address of the remote HLR: + remote-ip OSMOHLR_IP + ! default port is 4222, optionally configurable by: + remote-port 4222 +smpp + local-tcp-ip OSMOMSC_IP 2775 + policy accept-all + smpp-first +smsc + queue max-pending 20 + queue max-failure 1 + database delete-delivered 1 + database delete-expired 1 + validity-period minimum 1 + validity-period default 10080 + diff --git a/osmomsc/osmomsc_init.sh b/osmomsc/osmomsc_init.sh new file mode 100755 index 0000000..11fa018 --- /dev/null +++ b/osmomsc/osmomsc_init.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[ ${#MNC} == 3 ] && THREEGPP_REALM="mnc${MNC}.mcc${MCC}.3gppnetwork.org" || THREEGPP_REALM="mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +cp /mnt/osmomsc/osmo-msc.cfg /etc/osmocom + +sed -i 's|OSMOMSC_IP|'$OSMOMSC_IP'|g' /etc/osmocom/osmo-msc.cfg +sed -i 's|OSMOHLR_IP|'$OSMOHLR_IP'|g' /etc/osmocom/osmo-msc.cfg +sed -i 's|MNC|'$MNC'|g' /etc/osmocom/osmo-msc.cfg +sed -i 's|MCC|'$MCC'|g' /etc/osmocom/osmo-msc.cfg +sed -i 's|THREEGPP_REALM|'$THREEGPP_REALM'|g' /etc/osmocom/osmo-msc.cfg + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/pcf/pcf.yaml b/pcf/pcf.yaml new file mode 100644 index 0000000..1618faa --- /dev/null +++ b/pcf/pcf.yaml @@ -0,0 +1,30 @@ +db_uri: mongodb://MONGO_IP/open5gs + +logger: + file: + path: /open5gs/install/var/log/open5gs/pcf.log + +sbi: + server: + no_tls: true + client: + no_tls: true + +global: + max: + ue: MAX_NUM_UE + +pcf: + sbi: + server: + - address: PCF_IP + port: 7777 + client: + nrf: + - uri: http://NRF_IP:7777 + scp: + - uri: http://SCP_IP:7777 + metrics: + server: + - address: PCF_IP + port: 9091 diff --git a/pcf/pcf_init.sh b/pcf/pcf_init.sh new file mode 100755 index 0000000..afeaec6 --- /dev/null +++ b/pcf/pcf_init.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export DB_URI="mongodb://${MONGO_IP}/open5gs" + +cp /mnt/pcf/pcf.yaml install/etc/open5gs +sed -i 's|PCF_IP|'$PCF_IP'|g' install/etc/open5gs/pcf.yaml +sed -i 's|SCP_IP|'$SCP_IP'|g' install/etc/open5gs/pcf.yaml +sed -i 's|NRF_IP|'$NRF_IP'|g' install/etc/open5gs/pcf.yaml +sed -i 's|MONGO_IP|'$MONGO_IP'|g' install/etc/open5gs/pcf.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/pcf.yaml + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/pcrf/make_certs.sh b/pcrf/make_certs.sh new file mode 100755 index 0000000..9e4602d --- /dev/null +++ b/pcrf/make_certs.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +if [ 1 -ne $# ] +then + echo You must specify output directory : ./make_certs.sh ./freeDiameter + + exit; +fi + +rm -rf demoCA +mkdir demoCA +echo 01 > demoCA/serial +touch demoCA/index.txt.attr +touch demoCA/index.txt + +# Generate .rnd if it does not exist +openssl rand -out /root/.rnd -hex 256 + +# CA self certificate +openssl req -new -batch -x509 -days 3650 -nodes -newkey rsa:1024 -out $1/cacert.pem -keyout cakey.pem -subj /CN=ca.EPC_DOMAIN/C=KO/ST=Seoul/L=Nowon/O=Open5GS/OU=Tests + +#pcrf +openssl genrsa -out $1/pcrf.key.pem 1024 +openssl req -new -batch -out pcrf.csr.pem -key $1/pcrf.key.pem -subj /CN=pcrf.EPC_DOMAIN/C=KO/ST=Seoul/L=Nowon/O=Open5GS/OU=Tests +openssl ca -cert $1/cacert.pem -days 3650 -keyfile cakey.pem -in pcrf.csr.pem -out $1/pcrf.cert.pem -outdir . -batch + +rm -rf demoCA +rm -f 01.pem 02.pem 03.pem 04.pem +rm -f cakey.pem +rm -f pcrf.csr.pem diff --git a/pcrf/pcrf.conf b/pcrf/pcrf.conf new file mode 100644 index 0000000..d926cf9 --- /dev/null +++ b/pcrf/pcrf.conf @@ -0,0 +1,266 @@ +# This is a sample configuration file for freeDiameter daemon. + +# Most of the options can be omitted, as they default to reasonable values. +# Only TLS-related options must be configured properly in usual setups. + +# It is possible to use "include" keyword to import additional files +# e.g.: include "/etc/freeDiameter.d/*.conf" +# This is exactly equivalent as copy & paste the content of the included file(s) +# where the "include" keyword is found. + + +############################################################## +## Peer identity and realm + +# The Diameter Identity of this daemon. +# This must be a valid FQDN that resolves to the local host. +# Default: hostname's FQDN +#Identity = "aaa.koganei.freediameter.net"; +Identity = "pcrf.EPC_DOMAIN"; + +# The Diameter Realm of this daemon. +# Default: the domain part of Identity (after the first dot). +#Realm = "koganei.freediameter.net"; +Realm = "EPC_DOMAIN"; + +############################################################## +## Transport protocol configuration + +# The port this peer is listening on for incoming connections (TCP and SCTP). +# Default: 3868. Use 0 to disable. +Port = PCRF_BIND_PORT; + +# The port this peer is listening on for incoming TLS-protected connections (TCP and SCTP). +# See TLS_old_method for more information about TLS flavours. +# Note: we use TLS/SCTP instead of DTLS/SCTP at the moment. This will change in future version of freeDiameter. +# Default: 5868. Use 0 to disable. +#SecPort = 5868; + +# Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA exchange is completed +# on the unsecure connection. The alternative is RFC6733 mechanism, where TLS protects also the +# CER/CEA exchange on a dedicated secure port. +# This parameter only affects outgoing connections. +# The setting can be also defined per-peer (see Peers configuration section). +# Default: use RFC6733 method with separate port for TLS. +#TLS_old_method; + +# Disable use of TCP protocol (only listen and connect over SCTP) +# Default : TCP enabled +#No_TCP; + +# Disable use of SCTP protocol (only listen and connect over TCP) +# Default : SCTP enabled +#No_SCTP; +# This option is ignored if freeDiameter is compiled with DISABLE_SCTP option. + +# Prefer TCP instead of SCTP for establishing new connections. +# This setting may be overwritten per peer in peer configuration blocs. +# Default : SCTP is attempted first. +#Prefer_TCP; + +# Default number of streams per SCTP associations. +# This setting may be overwritten per peer basis. +# Default : 30 streams +#SCTP_streams = 30; + +############################################################## +## Endpoint configuration + +# Disable use of IP addresses (only IPv6) +# Default : IP enabled +#No_IP; + +# Disable use of IPv6 addresses (only IP) +# Default : IPv6 enabled +#No_IPv6; + +# Specify local addresses the server must bind to +# Default : listen on all addresses available. +#ListenOn = "202.249.37.5"; +#ListenOn = "2001:200:903:2::202:1"; +#ListenOn = "fe80::21c:5ff:fe98:7d62%eth0"; +ListenOn = "PCRF_IP"; + + +############################################################## +## Server configuration + +# How many Diameter peers are allowed to be connecting at the same time ? +# This parameter limits the number of incoming connections from the time +# the connection is accepted until the first CER is received. +# Default: 5 unidentified clients in paralel. +#ThreadsPerServer = 5; + +############################################################## +## TLS Configuration + +# TLS is managed by the GNUTLS library in the freeDiameter daemon. +# You may find more information about parameters and special behaviors +# in the relevant documentation. +# http://www.gnu.org/software/gnutls/manual/ + +# Credentials of the local peer +# The X509 certificate and private key file to use for the local peer. +# The files must contain PKCS-1 encoded RSA key, in PEM format. +# (These parameters are passed to gnutls_certificate_set_x509_key_file function) +# Default : NO DEFAULT +#TLS_Cred = "" , ""; +#TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key"; +TLS_Cred = "/open5gs/install/etc/freeDiameter/pcrf.cert.pem", "/open5gs/install/etc/freeDiameter/pcrf.key.pem"; + +# Certificate authority / trust anchors +# The file containing the list of trusted Certificate Authorities (PEM list) +# (This parameter is passed to gnutls_certificate_set_x509_trust_file function) +# The directive can appear several times to specify several files. +# Default : GNUTLS default behavior +#TLS_CA = ""; +TLS_CA = "/open5gs/install/etc/freeDiameter/cacert.pem"; + +# Certificate Revocation List file +# The information about revoked certificates. +# The file contains a list of trusted CRLs in PEM format. They should have been verified before. +# (This parameter is passed to gnutls_certificate_set_x509_crl_file function) +# Note: openssl CRL format might have interoperability issue with GNUTLS format. +# Default : GNUTLS default behavior +#TLS_CRL = ""; + +# GNU TLS Priority string +# This string allows to configure the behavior of GNUTLS key exchanges +# algorithms. See gnutls_priority_init function documentation for information. +# You should also refer to the Diameter required TLS support here: +# http://tools.ietf.org/html/rfc6733#section-13.1 +# Default : "NORMAL" +# Example: TLS_Prio = "NONE:+VERS-TLS1.1:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL"; +#TLS_Prio = "NORMAL"; + +# Diffie-Hellman parameters size +# Set the number of bits for generated DH parameters +# Valid value should be 768, 1024, 2048, 3072 or 4096. +# (This parameter is passed to gnutls_dh_params_generate2 function, +# it usually should match RSA key size) +# Default : 1024 +#TLS_DH_Bits = 1024; + +# Alternatively, you can specify a file to load the PKCS#3 encoded +# DH parameters directly from. This accelerates the daemon start +# but is slightly less secure. If this file is provided, the +# TLS_DH_Bits parameters has no effect. +# Default : no default. +#TLS_DH_File = ""; + + +############################################################## +## Timers configuration + +# The Tc timer of this peer. +# It is the delay before a new attempt is made to reconnect a disconnected peer. +# The value is expressed in seconds. The recommended value is 30 seconds. +# Default: 30 +#TcTimer = 30; + +# The Tw timer of this peer. +# It is the delay before a watchdog message is sent, as described in RFC 3539. +# The value is expressed in seconds. The default value is 30 seconds. Value must +# be greater or equal to 6 seconds. See details in the RFC. +# Default: 30 +#TwTimer = 30; + +############################################################## +## Applications configuration + +# Disable the relaying of Diameter messages? +# For messages not handled locally, the default behavior is to forward the +# message to another peer if any is available, according to the routing +# algorithms. In addition the "0xffffff" application is advertised in CER/CEA +# exchanges. +# Default: Relaying is enabled. +NoRelay; + +# Number of server threads that can handle incoming messages at the same time. +# Default: 4 +#AppServThreads = 4; + +# Other applications are configured by loaded extensions. + +############################################################## +## Extensions configuration + +# The freeDiameter framework merely provides support for +# Diameter Base Protocol. The specific application behaviors, +# as well as advanced functions, are provided +# by loadable extensions (plug-ins). +# These extensions may in addition receive the name of a +# configuration file, the format of which is extension-specific. +# +# Format: +#LoadExtension = "/path/to/extension" [ : "/optional/configuration/file" ] ; +# +# Examples: +#LoadExtension = "extensions/sample.fdx"; +#LoadExtension = "extensions/sample.fdx":"conf/sample.conf"; + +# Extensions are named as follow: +# dict_* for extensions that add content to the dictionary definitions. +# dbg_* for extensions useful only to retrieve more information on the framework execution. +# acl_* : Access control list, to control which peers are allowed to connect. +# rt_* : routing extensions that impact how messages are forwarded to other peers. +# app_* : applications, these extensions usually register callbacks to handle specific messages. +# test_* : dummy extensions that are useful only in testing environments. + + +# The dbg_msg_dump.fdx extension allows you to tweak the way freeDiameter displays some +# information about some events. This extension does not actually use a configuration file +# but receives directly a parameter in the string passed to the extension. Here are some examples: +## LoadExtension = "dbg_msg_dumps.fdx" : "0x1111"; # Removes all default hooks, very quiet even in case of errors. +## LoadExtension = "dbg_msg_dumps.fdx" : "0x2222"; # Display all events with few details. +## LoadExtension = "dbg_msg_dumps.fdx" : "0x0080"; # Dump complete information about sent and received messages. +# The four digits respectively control: connections, routing decisions, sent/received messages, errors. +# The values for each digit are: +# 0 - default - keep the default behavior +# 1 - quiet - remove any specific log +# 2 - compact - display only a summary of the information +# 4 - full - display the complete information on a single long line +# 8 - tree - display the complete information in an easier to read format spanning several lines. + +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dbg_msg_dumps.fdx" : "0x8888"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_rfc5777.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_mip6i.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_nasreq.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_nas_mipv6.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_dcca.fdx"; +LoadExtension = "LD_LIBRARY_PATH/freeDiameter/dict_dcca_3gpp.fdx"; + + +############################################################## +## Peers configuration + +# The local server listens for incoming connections. By default, +# all unknown connecting peers are rejected. Extensions can override this behavior (e.g., acl_wl). +# +# In addition to incoming connections, the local peer can +# be configured to establish and maintain connections to some +# Diameter nodes and allow connections from these nodes. +# This is achieved with the ConnectPeer directive described below. +# +# Note that the configured Diameter Identity MUST match +# the information received inside CEA, or the connection will be aborted. +# +# Format: +#ConnectPeer = "diameterid" [ { parameter1; parameter2; ...} ] ; +# Parameters that can be specified in the peer's parameter list: +# No_TCP; No_SCTP; No_IP; No_IPv6; Prefer_TCP; TLS_old_method; +# No_TLS; # assume transparent security instead of TLS. DTLS is not supported yet (will change in future versions). +# Port = 5868; # The port to connect to +# TcTimer = 30; +# TwTimer = 30; +# ConnectTo = "202.249.37.5"; +# ConnectTo = "2001:200:903:2::202:1"; +# TLS_Prio = "NORMAL"; +# Realm = "realm.net"; # Reject the peer if it does not advertise this realm. +# Examples: +#ConnectPeer = "aaa.wide.ad.jp"; +#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; Port=3868; } ; +ConnectPeer = "smf.EPC_DOMAIN" { ConnectTo = "SMF_IP"; Port = 3868; No_TLS; }; +ConnectPeer = "pcscf.IMS_DOMAIN" { ConnectTo = "PCSCF_IP"; Port = PCSCF_BIND_PORT; No_TLS; }; + +############################################################## diff --git a/pcrf/pcrf.yaml b/pcrf/pcrf.yaml new file mode 100644 index 0000000..0af516c --- /dev/null +++ b/pcrf/pcrf.yaml @@ -0,0 +1,12 @@ +db_uri: mongodb://MONGO_IP/open5gs + +logger: + file: + path: /open5gs/install/var/log/open5gs/pcrf.log + +global: + max: + ue: MAX_NUM_UE + +pcrf: + freeDiameter: /open5gs/install/etc/freeDiameter/pcrf.conf diff --git a/pcrf/pcrf_init.sh b/pcrf/pcrf_init.sh new file mode 100755 index 0000000..a13ccb7 --- /dev/null +++ b/pcrf/pcrf_init.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +export IP_ADDR=$(awk 'END{print $1}' /etc/hosts) +export DB_URI="mongodb://${MONGO_IP}/open5gs" + +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +cp /mnt/pcrf/pcrf.yaml install/etc/open5gs +cp /mnt/pcrf/pcrf.conf install/etc/freeDiameter +cp /mnt/pcrf/make_certs.sh install/etc/freeDiameter + +sed -i 's|MONGO_IP|'$MONGO_IP'|g' install/etc/open5gs/pcrf.yaml +sed -i 's|MAX_NUM_UE|'$MAX_NUM_UE'|g' install/etc/open5gs/pcrf.yaml +sed -i 's|PCRF_IP|'$PCRF_IP'|g' install/etc/freeDiameter/pcrf.conf +sed -i 's|SMF_IP|'$SMF_IP'|g' install/etc/freeDiameter/pcrf.conf +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' install/etc/freeDiameter/pcrf.conf +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' install/etc/freeDiameter/pcrf.conf +sed -i 's|PCRF_BIND_PORT|'$PCRF_BIND_PORT'|g' install/etc/freeDiameter/pcrf.conf +sed -i 's|PCSCF_IP|'$PCSCF_IP'|g' install/etc/freeDiameter/pcrf.conf +sed -i 's|PCSCF_BIND_PORT|'$PCSCF_BIND_PORT'|g' install/etc/freeDiameter/pcrf.conf +sed -i 's|LD_LIBRARY_PATH|'$LD_LIBRARY_PATH'|g' install/etc/freeDiameter/pcrf.conf +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' install/etc/freeDiameter/make_certs.sh + +# Generate TLS certificates +./install/etc/freeDiameter/make_certs.sh install/etc/freeDiameter + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/pcscf/dispatcher.list b/pcscf/dispatcher.list new file mode 100644 index 0000000..47d4d4f --- /dev/null +++ b/pcscf/dispatcher.list @@ -0,0 +1 @@ +# SBC's diff --git a/pcscf/kamailio_pcscf.cfg b/pcscf/kamailio_pcscf.cfg new file mode 100644 index 0000000..31ea43b --- /dev/null +++ b/pcscf/kamailio_pcscf.cfg @@ -0,0 +1,1204 @@ +# +# TelcoSuite (V3) Proxy-CSCF +# +# Kamailio (OpenSER) SIP Server +# - web: http://www.kamailio.org +# - git: http://sip-router.org +# +# Refer to the Core CookBook at http://www.kamailio.org/dokuwiki/doku.php +# for an explanation of possible statements, functions and parameters. +# + +import_file "pcscf.cfg" + +####### Defined Values ######### +# *** Value defines - IDs used later in config +#!define DISPATCHER_LIST_SBC 1 + +#!define DISPATCHER_DST_AVP "i:1" +#!define DISPATCHER_GRP_AVP "i:2" +#!define DISPATCHER_CNT_AVP "i:3" +#!define DISPATCHER_SOCK_AVP "i:4" + +#!define RR_CUSTOM_USER_AVP "i:5" +#!define DLG_TIMEOUT_AVP "i:6" + +#!define FLT_MOBILE_ORIG 1 +#!define FLT_DIALOG 2 +#!define FLT_NAT 3 +#!define FLT_RTP 4 +#!define FLT_CAPTURE 5 + +####### Global Parameters ######### +debug=2 +log_stderror=no + +memdbg=5 +memlog=5 + +max_while_loops=5000 + +#!ifdef WITH_XMLRPC +listen=tcp:127.0.0.1:5060 +#!endif + +# Locks all ser pages into memory making it unswappable (in general one +# doesn't want his sip proxy swapped out ) +mlock_pages=yes +# Tries to pre-fault all the shared memory, before starting. When "on", start +# time will increase, but combined with mlock_pages will guarantee ser will get +# all its memory from the beginning (no more kswapd slow downs) +shm_force_alloc=yes + +# Do SRV-Loadbalancing: +dns_srv_lb=on +# Always prefer IPv6: +dns_try_ipv6=on +# Always prefer IPv6: +dns_cache_flags=4 +# DNS-Based failover +use_dns_failover=on +# Query NAPTR-Records as well: +dns_try_naptr=off +# DNS cache won't be used (all dns lookups will result into a DNS request) +use_dns_cache=off + +user_agent_header="User-Agent: TelcoSuite Proxy-CSCF" +server_header="Server: TelcoSuite Proxy-CSCF" + +log_facility=LOG_LOCAL0 +log_name="pcscf" +log_prefix_mode=1 +log_prefix="{$mt $hdr(CSeq) $ci $cfg(route)} " + +fork=yes +children=4 + +#!ifndef TCP_PROCESSES +# Number of TCP Processes +#!define TCP_PROCESSES 16 +#!endif + +#!ifdef WITH_TLS +# Check, if TCP is enabled: +#!ifndef WITH_TCP +#!define WITH_TCP +#!endif +enable_tls=yes +#!endif + +#!ifdef WITH_XMLRPC +#!ifndef WITH_TCP +#!define WITH_TCP +#!endif +#!ifndef TCP_PROCESSES +# Number of TCP Processes +#!define TCP_PROCESSES 3 +#!endif +#!endif + +#!ifdef WITH_TCP +# life time of TCP connection when there is no traffic +# - a bit higher than registration expires to cope with UA behind NAT +tcp_connection_lifetime=UE_SUBSCRIPTION_EXPIRES +# If a message received over a tcp connection has "alias" in its via a new tcp +# alias port will be created for the connection the message came from (the +# alias port will be set to the via one). +# +# Note: For NAT traversal of TCP clients it is better to not use +# tcp_accept_aliases but just use nathelper module and +# fix_nated_[contact|register] functions. +tcp_accept_aliases=no +# Enable SIP outbound TCP keep-alive using PING-PONG (CRLFCRLF - CRLF). +tcp_crlf_ping=yes + +tcp_reuse_port=yes + +tcp_accept_no_cl=yes +tcp_rd_buf_size=16384 + +#!ifdef TCP_PROCESSES +tcp_children=TCP_PROCESSES +#!endif +#!else +disable_tcp=yes +#!endif + +/* uncomment the next line to disable the auto discovery of local aliases + based on reverse DNS on IPs (default on) */ +auto_aliases=no + +#phone2tel=1 + +udp_mtu = 1300 +udp_mtu_try_proto = TCP + +/* uncomment and configure the following line if you want Kamailio to + bind on a specific interface/port/proto (default bind on all available) */ + +system.shutdownmode = 0 desc "System shutdown mode" +system.service = "Proxy-CSCF" desc "Function of this server" + +####### Modules Section ######## + +# set paths to location of modules +mpath="/usr/lib64/kamailio/modules_k/:/usr/lib64/kamailio/modules/:/usr/lib/kamailio/modules_k/:/usr/lib/kamailio/modules/:/usr/lib/x86_64-linux-gnu/kamailio/modules/:/usr/local/lib64/kamailio/modules" + +# Fifo Module +# Kamailio Extensions (e.g. MI:uptime, MI:version, cfg:isflagset etc.) +loadmodule "kex.so" +loadmodule "corex.so" +# Transaction Module +loadmodule "tm.so" +loadmodule "tmx.so" +loadmodule "sl.so" +loadmodule "rr.so" +loadmodule "pv.so" +loadmodule "maxfwd.so" +loadmodule "textops.so" +loadmodule "textopsx.so" +# SIP-Utilities: options_reply +loadmodule "siputils.so" +loadmodule "sanity.so" +loadmodule "ctl.so" +loadmodule "cfg_rpc.so" +loadmodule "xlog.so" +loadmodule "auth.so" +loadmodule "dispatcher.so" +loadmodule "sctp.so" +loadmodule "path.so" +loadmodule "statistics.so" + +loadmodule "ims_dialog.so" +loadmodule "ims_usrloc_pcscf.so" +# Following module is required even in case of IPSec being disabled. +loadmodule "ims_ipsec_pcscf.so" +loadmodule "ims_registrar_pcscf.so" + +#!ifdef WITH_XMLRPC +loadmodule "xmlrpc.so" +#!endif + +#!ifdef WITH_REGINFO +loadmodule "pua.so" +#!endif + +#!ifdef DB_URL +loadmodule "db_mysql.so" +#!ifdef DB_URL2 +loadmodule "db_cluster.so" +#!endif +#!endif + +#!ifdef WITH_DEBUG +loadmodule "debugger.so" +#!endif + +loadmodule "usrloc.so" +loadmodule "registrar.so" +loadmodule "rtimer.so" +loadmodule "nathelper.so" + +#!ifdef WITH_ANTIFLOOD +loadmodule "pike.so" +#!endif + +#!ifdef WITH_TLS +loadmodule "tls.so" +#!endif + +#!ifdef WITH_RTPPING +loadmodule "rtpping.so" +#!endif + + +loadmodule "sdpops.so" +loadmodule "rtpengine.so" + +#!ifdef WITH_WEBSOCKET +loadmodule "xhttp.so" +loadmodule "websocket.so" +#!endif + +#!ifdef WITH_RX +loadmodule "cdp.so" +loadmodule "cdp_avp.so" +loadmodule "ims_qos.so" +#!endif + +#!ifdef WITH_N5 +loadmodule "http_client.so" +loadmodule "jansson.so" +loadmodule "nghttp2.so" +loadmodule "uuid.so" +#!endif + +#!ifdef CAPTURE_NODE +loadmodule "siptrace.so" +#!endif + +#!ifdef WITH_NATPING +loadmodule "uac.so" +loadmodule "sqlops.so" +#!endif + +# HTable as a cache: +loadmodule "htable.so" + +#!ifdef WITH_DEBUG +#loadmodule "debugger.so" +modparam("debugger", "mod_hash_size", 5) +modparam("debugger", "mod_level_mode", 1) +modparam("debugger", "mod_level", "xlog=3") +modparam("debugger", "mod_level", "rtpengine=3") +modparam("debugger", "mod_level", "ims_qos=3") +#!ifdef WITH_IPSEC +modparam("debugger", "mod_level", "ims_ipsec_pcscf=3") +#!endif +modparam("debugger", "mod_level", "textops=3") +modparam("debugger", "mod_level", "tm=3") +modparam("debugger", "mod_level", "ims_registrar_pcscf=3") +modparam("debugger", "mod_level", "ims_usrloc_pcscf=3") +#!ifdef WITH_DEBUG_TRACE +modparam("debugger", "cfgtrace", 1) +#!endif +#!endif + +loadmodule "jsonrpcs.so" +# ----- jsonrpcs params ----- +modparam("jsonrpcs", "pretty_format", 1) +/* set the path to RPC fifo control file */ +modparam("jsonrpcs", "fifo_name", "/var/run/kamailio/kamailio_rpc.fifo") +/* set the path to RPC unix socket control file */ +modparam("jsonrpcs", "dgram_socket", "/var/run/kamailio/kamailio_rpc.sock") + +# ----------------- setting module-specific parameters --------------- +#!ifdef DB_URL2 +# ----- db_cluster params ----- +modparam("db_cluster", "connection", DB_URL) +modparam("db_cluster", "connection", DB_URL2) +modparam("db_cluster", "cluster", "cluster1=>con1=2s2s;con2=1s1s") +#!endif + +#!ifdef WITH_ANTIFLOOD +# ----- pike params ----- +modparam("pike", "sampling_time_unit", 2) +modparam("pike", "reqs_density_per_unit", 16) +modparam("pike", "remove_latency", 4) + +# ----- htable params ----- +# ip ban htable with autoexpire after 5 minutes +modparam("htable", "htable", "ipban=>size=8;autoexpire=300") +modparam("htable", "htable", "failedauth=>size=8;autoexpire=120") +modparam("htable", "htable", "natpingfrom=>size=8;autoexpire=UE_SUBSCRIPTION_EXPIRES;") +#!endif + +modparam("htable", "htable", "a=>size=8;autoexpire=20") + +#!ifdef WITH_IMS_HDR_CACHE +modparam("htable", "htable", "serviceroutes=>size=16;autoexpire=UE_SUBSCRIPTION_EXPIRES;") +modparam("htable", "htable", "associateduris=>size=16;autoexpire=UE_SUBSCRIPTION_EXPIRES;") +#!endif + +#!ifdef WITH_NATPING +modparam("htable", "htable", "natping=>size=8;autoexpire=UE_SUBSCRIPTION_EXPIRES;") +modparam("htable", "htable", "natpingfail=>size=8;autoexpire=UE_SUBSCRIPTION_EXPIRES;") +modparam("htable", "htable", "natpingfrom=>size=8;autoexpire=UE_SUBSCRIPTION_EXPIRES;") +#!ifdef DB_URL2 +modparam("sqlops","sqlcon","pcscf=>cluster://cluster1") +#!else +modparam("sqlops","sqlcon", SQLOPS_DBURL) +#!endif + +modparam("uac","restore_mode","none") + +# ----------------- Settings for RTimer --------------- +# time interval set to 60 seconds +modparam("rtimer", "timer", "name=NATPING;interval=5;mode=1;") +modparam("rtimer", "exec", "timer=NATPING;route=NATPING") +#!endif + +# ----- tm params ----- +# auto-discard branches from previous serial forking leg +#modparam("tm", "failure_reply_mode", 3) +# default retransmission timeout: 3 sec +modparam("tm", "fr_timer", 3000) +# default invite retransmission timeout after 1xx: 120sec +modparam("tm", "fr_inv_timer", 120000) +# Dont reply automatically with "100 Trying" +modparam("tm", "auto_inv_100", 0) + +# ----- rr params ----- +# add value to ;lr param to cope with most of the UAs +modparam("rr", "enable_full_lr", 1) +# do not append from tag to the RR (no need for this script) +modparam("rr", "append_fromtag", 1) +# add a Username to RR-Header +modparam("rr", "add_username", 1) +# Take User from a custom AVP +modparam("rr", "custom_user_avp", "$avp(RR_CUSTOM_USER_AVP)") +modparam("rr", "force_send_socket", 1) + +#!ifdef WITH_XMLRPC +# ----- xmlrpc params ----- +modparam("xmlrpc", "route", "XMLRPC"); +modparam("xmlrpc", "url_match", "^/RPC") +#!endif + +#!ifdef WITH_TLS +# ----- tls params ----- +modparam("tls", "config", "/etc/kamailio_pcscf/tls.cfg") +#!endif + +# ----- rtpproxy params ----- +modparam("rtpengine", "setid_default", 1) +modparam("rtpengine", "rtpengine_sock", "1 == udp:RTPENGINE_IP:2223") +#modparam("rtpengine", "rtpengine_sock", "2 == udp:localhost:2224") +modparam("rtpengine", "setid_avp", "$avp(setid)") +modparam("rtpengine", "extra_id_pv", "$avp(extra_id)") + +modparam("path", "use_received", 1) + +# ----- ctl params ----- +modparam("ctl", "binrpc", "unix:/var/run/kamailio/kamailio_ctl") + +# ----------------- Settings for Dispatcher --------------- +modparam("dispatcher", "list_file", "/etc/kamailio_pcscf/dispatcher.list") + +# Dispatcher: Enable Failover-Support +modparam("dispatcher", "flags", 2) +# Dispatcher: Overwrite Destination address, if required. +modparam("dispatcher", "force_dst", 1) +# AVP's required for Fail-Over-Support: +#modparam("dispatcher", "dst_avp", "$avp(DISPATCHER_DST_AVP)") +#modparam("dispatcher", "grp_avp", "$avp(DISPATCHER_GRP_AVP)") +#modparam("dispatcher", "cnt_avp", "$avp(DISPATCHER_CNT_AVP)") +#modparam("dispatcher", "sock_avp", "$avp(DISPATCHER_SOCK_AVP)") + +#modparam("dispatcher", "xavp_dst", "$avp(DISPATCHER_DST_AVP)") +#modparam("dispatcher", "xavp_dst_mode", 0) +#modparam("dispatcher", "xavp_ctx", "$avp(DISPATCHER_CNT_AVP)") +#modparam("dispatcher", "xavp_ctx_mode", 0) + +# Try to recover disabled destinations every 15 seconds. +modparam("dispatcher", "ds_ping_interval", 15) +# Actively query the gateways: +modparam("dispatcher", "ds_probing_mode", 1) + +# -- usrloc params -- +#!ifdef DB_URL +#!ifdef DB_URL2 +modparam("ims_usrloc_pcscf", "db_url", "cluster://cluster1") +#!else +modparam("ims_usrloc_pcscf", "db_url", DB_URL) +#!endif +modparam("ims_usrloc_pcscf", "db_mode", 0) +#!endif +#modparam("ims_usrloc_pcscf", "hashing_type", 2) +modparam("ims_usrloc_pcscf", "enable_debug_file", 0) +modparam("ims_usrloc_pcscf", "match_contact_host_port", 1) +modparam("ims_registrar_pcscf", "is_registered_fallback2ip", 1) +modparam("ims_registrar_pcscf", "ignore_reg_state", 1) +modparam("ims_registrar_pcscf", "ignore_contact_rxport_check", 1) +modparam("ims_registrar_pcscf", "pending_reg_expires", 30) +modparam("ims_registrar_pcscf", "subscription_expires", UE_SUBSCRIPTION_EXPIRES) +modparam("ims_registrar_pcscf", "delete_delay", CONTACT_DELETE_DELAY) +modparam("ims_usrloc_pcscf", "expires_grace", 120) + +#!ifdef WITH_REGINFO +modparam("ims_registrar_pcscf", "subscribe_to_reginfo", 1) +modparam("ims_registrar_pcscf", "publish_reginfo", 1) +modparam("ims_registrar_pcscf", "pcscf_uri", "sip:HOSTNAME") +#!else +modparam("ims_registrar_pcscf", "subscribe_to_reginfo", 0) +modparam("ims_registrar_pcscf", "publish_reginfo", 0) +#!endif + +#!ifdef WITH_IPSEC +modparam("ims_ipsec_pcscf", "ipsec_listen_addr", IPSEC_LISTEN_ADDR) +modparam("ims_ipsec_pcscf", "ipsec_client_port", IPSEC_CLIENT_PORT) +modparam("ims_ipsec_pcscf", "ipsec_server_port", IPSEC_SERVER_PORT) +modparam("ims_ipsec_pcscf", "ipsec_spi_id_start", 4096) +modparam("ims_ipsec_pcscf", "ipsec_max_connections", IPSEC_MAX_CONN) +modparam("ims_ipsec_pcscf", "ipsec_preferred_ealg", "null") +modparam("htable", "htable", "ipsec_clients=>size=8;autoexpire=UE_SUBSCRIPTION_EXPIRES;") +#!endif + +#!ifdef WITH_RX +# -- CDP params -- +modparam("cdp","config_file","/etc/kamailio_pcscf/pcscf.xml") +# -- diameter_rx params -- +modparam("ims_qos", "rx_dest_realm", "PCRF_REALM") +modparam("ims_qos", "early_qosrelease_reason", "Sorry - QoS failed") +modparam("ims_qos", "confirmed_qosrelease_headers", "X-Reason: QoS failed\r\n") +modparam("ims_qos", "authorize_video_flow", 1) +modparam("ims_qos", "af_signaling_ip", RX_AF_SIGNALING_IP) +modparam("ims_qos", "include_rtcp_fd", 1) +modparam("ims_qos", "rx_auth_expiry", UE_SUBSCRIPTION_EXPIRES) +modparam("ims_qos", "recv_mode", 1) +modparam("ims_qos", "dialog_direction", RX_IMS_REG_DIALOG_DIRECTION) +#!endif + +#!ifdef WITH_N5 + +# Tables to store users and their session details +modparam("htable", "htable", "user_data=>size=8;autoexpire=3600;") +modparam("htable", "htable", "user_ids=>size=8;autoexpire=3600;") +modparam("htable", "htable", "user_sdps_ip=>size=8;autoexpire=3600;") +modparam("htable", "htable", "user_sdps_port=>size=8;autoexpire=3600;") +modparam("htable", "htable", "user_sdps_rtcp_port=>size=8;autoexpire=3600;") +modparam("htable", "htable", "user_sip_ips=>size=8;autoexpire=3600;") +modparam("htable", "htable", "user_sip_ports=>size=8;autoexpire=3600;") + +# HTTP2 for 5G -- Modules Parameters +modparam("http_client", "httpredirect", 1) +modparam("http_client", "useragent", "AF") +modparam("http_client", "maxdatasize", 64535) +modparam("http_client", "connection_timeout", 2) +modparam("http_client", "keep_connections", 1) +modparam("http_client", "response_headers", 1) +modparam("http_client", "query_result", 1) +modparam("nghttp2", "listen_addr", "N5_BIND_IP") +modparam("nghttp2", "listen_port", "N5_BIND_PORT") +# Replace the following with your own Key and Cert, you can use HAProxy to terminate TLS towards Clients e.g. Open5gs PCF +# modparam("nghttp2", "tls_private_key", "/mnt/pcscf/http2_key.pem") +# modparam("nghttp2", "tls_public_key", "/mnt/pcscf/http2_tr.pem") + +modparam("rtimer", "timer", "name=NRF_NFM;interval=5;mode=1;") +modparam("rtimer", "exec", "timer=NRF_NFM;route=NRF_NFM") +#!endif + +# -- pua params -- +#!ifdef WITH_REGINFO +#!ifdef DB_URL +#!ifdef DB_URL2 +modparam("pua", "db_url", "cluster://cluster1") +#!else +modparam("pua", "db_url", DB_URL) +#!endif +#!endif +#!endif + +# -- ims_dialog params -- +modparam("ims_dialog", "dlg_flag", FLT_DIALOG) +modparam("ims_dialog", "timeout_avp", "$avp(DLG_TIMEOUT_AVP)") +modparam("ims_dialog", "detect_spirals", 0) +modparam("ims_dialog", "profiles_no_value", "orig ; term") +modparam("ims_dialog", "profiles_with_value", "caller ; callee") +#!ifdef DB_URL +#!ifdef DB_URL2 +modparam("ims_dialog", "db_url", "cluster://cluster1") +#!else +modparam("ims_dialog", "db_url", DB_URL) +#!endif +modparam("ims_dialog", "db_mode", 0) +#!endif + +#!ifdef CAPTURE_NODE +# Destination, where to send the traffic +modparam("siptrace", "duplicate_uri", CAPTURE_NODE) +# Trace all traffic +modparam("siptrace", "trace_on", 1) +modparam("siptrace", "trace_to_database", 0) +modparam("siptrace", "trace_flag", FLT_CAPTURE) +modparam("siptrace", "hep_mode_on", 1) +#!endif + +# -- statistics params -- +modparam("statistics", "variable", "register_success") +modparam("statistics", "variable", "register_failed") +modparam("statistics", "variable", "register_time") + +# Main SIP request routing logic +# - processing of any incoming SIP request starts with this route +route { +##!ifdef WITH_DEBUG + xnotice("PCSCF: $rm $ru ($fu ($si:$sp) to $tu, $ci)\n"); +##!endif + +#!ifdef WITH_WEBSOCKET + if (($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT) && !(proto == WS || proto == WSS)) { + xlog("L_WARN", "Websocket-request received on SIP/$Rp\n"); + sl_send_reply("403", "Forbidden - Websocket-request received on SIP/$Rp"); + exit; + } +#!endif + # per request initial checks + route(REQINIT); + +#!ifdef WITH_IPSEC + if (is_request() && is_method("REGISTER")) { + sht_lock("ipsec_clients=>ipsec_clients_lock"); + $sht(ipsec_clients=>$si) = $null; + if ($hdrc(Security-Client) == 1) { + $sht(ipsec_clients=>$si) = 1; + } + sht_unlock("ipsec_clients=>ipsec_clients_lock"); + } +#!endif + + # CANCEL processing + if (is_method("CANCEL")) { + if (t_check_trans()) { + t_relay(); + } + exit; + } + + if (is_method("NOTIFY") && (uri==myself)) { + route(NOTIFY); + exit; + } + + # handle retransmissions + if (!is_method("ACK")) { + if(t_precheck_trans()) { + t_check_trans(); + exit; + } + } + #t_check_trans(); + + # Check for Re-Transmissions + t_check_trans(); + + # handle requests within SIP dialogs + route(WITHINDLG); + + ### only initial requests (no To tag) + + if (is_method("UPDATE")) { + send_reply("403","Forbidden - Target refresh outside dialog not allowed"); + break; + } + if (is_method("BYE|PRACK")) { + send_reply("403","Forbidden - Originating subsequent requests outside dialog not allowed"); + break; + } + + #Set DLG flag to track dialogs using dialog2 + if (!is_method("REGISTER|SUBSCRIBE")) + setflag(FLT_DIALOG); + + loose_route(); +#!ifdef WITH_SBC + if (ds_is_from_list(DISPATCHER_LIST_SBC)) { + if (is_method("INVITE")) { + if (is_present_hf("C-Params")) { + remove_hf("Contact"); + remove_hf("C-Params"); + append_hf("Contact: $ct;$hdr(C-Params)\r\n"); + } + if ($route_uri =~ "sip:mo@.*") { + # prepend mo as user for record route + $avp(RR_CUSTOM_USER_AVP)="mo"; + if (is_present_hf("P-Route")) { + $du = $(hdr(P-Route){nameaddr.uri}); + remove_hf("P-Route"); + append_hf("Route: $hdr(P-Route)\r\n"); + } + t_on_reply("SBC_GET_CPARAMS"); + } + if ($route_uri =~ "sip:mt@.*") { + $du = $ru; + handle_ruri_alias(); + if ($rc == 1) { + setflag(FLT_NAT); + } + xlog("$$dP => $(dP{s.tolower}) ($du)\n"); + # prepend mo as user for record route + $avp(RR_CUSTOM_USER_AVP)="mt"; + if ($(dP{s.tolower}) == "tls") { + route(ENC_SRTP); + } else if ($(dP{s.tolower}) == "ws") { + # Even WSS is incorrectly shown as WS + route(ENC_WSS_RTP); + } else if ($(dP{s.tolower}) == "wss") { + route(ENC_WSS_RTP); + } else { + route(ENC_RTP); + } + # Handle NAT + route(NATMANAGE); + # Handle Mobile Terminated requests + route(MT); + } + } + if (is_method("REGISTER")) { + append_hf("Path: \r\n"); + } + } else { +#!endif + if ($route_uri =~ "sip:term@.*") { +#!ifdef WITH_SBC +#!ifdef WITH_SBC_CALL + if (is_method("INVITE")) { +#!endif + if (!strempty($(ct{tobody.params}))) { + append_hf("C-Params: $(ct{tobody.params})\r\n"); + } + + append_hf("SBC: mt\r\n"); + # Do some Round-Robin on the SBC's + t_on_failure("SBC_failure"); + # Choose an SBC to send the call to: + if (!ds_select_dst(DISPATCHER_LIST_SBC, "4")) { + send_reply("503", "Service Unavailable (SBC failure)"); + exit; + } +#!ifdef WITH_SBC_CALL + } +#!endif +#!else + handle_ruri_alias(); + if ($dP == "tls") { + route(ENC_SRTP); + } else if ($dP == "ws") { + route(ENC_WS_RTP); + } else if ($dP == "wss") { + route(ENC_WSS_RTP); + } else { + route(ENC_RTP); + } + if ($rc == 1) { + setflag(FLT_NAT); + } + # Handle NAT + route(NATMANAGE); + # prepend mo as user for record route + $avp(RR_CUSTOM_USER_AVP)="mt"; + route(MT); +#!endif + } else { + force_rport(); + if(is_method("INVITE|REGISTER")) { + add_contact_alias(); + } + setflag(FLT_NAT); + + if (is_method("REGISTER")) { + route(REGISTER); + exit; + } + + # prepend mo as user for record route + $avp(RR_CUSTOM_USER_AVP)="mo"; + # Set Flag for MO: + setflag(FLT_MOBILE_ORIG); + # Increase timer for inbound requests, we may have to do failover: + t_set_fr(120000, 30000); + route(MO); + if (is_method("INVITE")) { + # SRTP in RTP übersetzen + if ($pr == "tls") { + route(DEC_SRTP); + } else if ($pr == "ws") { + route(DEC_WS_RTP); + } else if ($pr == "wss") { + route(DEC_WSS_RTP); + } else { + route(DEC_RTP); + } + # Handle NAT + route(NATMANAGE); + } +#!ifdef WITH_SBC +#!ifdef WITH_SBC_CALL + if (is_method("INVITE")) { +#!endif + # Apply changes to this message + msg_apply_changes(); + # Copy Route-Header: + append_hf("P-Route: $hdr(Route)\r\n"); + if (!strempty($(ct{tobody.params}))) { + append_hf("C-Params: $(ct{tobody.params})\r\n"); + } + append_hf("SBC: mo\r\n"); + # Do some Round-Robin on the SBC's + t_on_failure("SBC_failure"); + # Choose an SBC to send the call to: + if (!ds_select_dst(DISPATCHER_LIST_SBC, "4")) { + send_reply("503", "Service Unavailable (SBC failure)"); + exit; + } +#!endif +#!ifdef WITH_SBC_CALL + } +#!endif + } +#!ifdef WITH_SBC + } +#!endif + if (is_method("INVITE|SUBSCRIBE")) { + # record routing for dialog forming requests (in case they are routed) + record_route(); + } + + # Forward request: + route(RELAY); + exit; +} + +route[SBC_GET_CPARAMS] { + if (!strempty($(ct{tobody.params}))) { + append_hf("C-Params: $(ct{tobody.params})\r\n"); + } +} + +# Per SIP request initial checks +route[REQINIT] { + # Reply to OPTIONS: + if (is_method("OPTIONS") && (uri==myself)) { + options_reply(); + exit; + } + + $var(used) = 1 - ($stat(free_size) / $stat(total_size)); + xlog("L_DBG", "Mem: Total $stat(total_size), Free $stat(free_size) [$var(used)% used]\n"); + if ($var(used) > 95) { + send_reply("503", "Server overloaded"); + exit; + } + + # Trace this message +#!ifdef CAPTURE_NODE + sip_trace(); + setflag(FLT_CAPTURE); +#!endif + +#!ifdef WITH_ANTIFLOOD + # flood dection from same IP and traffic ban for a while + # be sure you exclude checking trusted peers, such as pstn gateways + # - local host excluded (e.g., loop to self) + if (!has_totag() && (src_ip!=myself) && !ds_is_from_list()) + { + if($sht(ipban=>$si)!=$null) + { + # ip is already blocked + xlog("request from blocked IP - $rm from $fu (IP:$si:$sp)\n"); + xlog("Blocking traffic from $si\n"); + exit; + } + if (!pike_check_req()) { + xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp, $ua)\n"); + xlog("Blocking traffic from $si\n"); + $sht(ipban=>$si) = 1; + exit; + } + } + if ((uri == myself) && is_method("INVITE|REGISTER")) { + xlog("L_ALERT","ALERT: Request to myself: $ru from $fu (IP:$si:$sp, $ua), Blocking\n"); + xlog("Blocking traffic from $si\n"); + $sht(ipban=>$si) = 1; + exit; + } +#!endif + + if (!mf_process_maxfwd_header("10")) { + sl_send_reply("483","Too Many Hops"); + exit; + } + + if(!sanity_check("1511", "7")) { + xlog("Malformed SIP message from $si:$sp\n"); + exit; + } + + # Check for shutdown mode: + if (!has_totag() && ($sel(cfg_get.system.shutdownmode) > 0)) { + send_reply("503", "Server shutting down"); + exit; + } + + # Ignore Re-Transmits: + if (t_lookup_request()) { + exit; + } + + if (is_method("INVITE|REGISTER")) { + send_reply("100", "Trying"); + } +} + +route[RELAY] { + if (!t_relay()) { + sl_reply_error(); + } + exit; +} + +# Handle requests within SIP dialogs +route[WITHINDLG] { + if (has_totag()) { + xnotice("Within DLG\n"); + # sequential request withing a dialog should + # take the path determined by record-routing + if (loose_route()) { + xnotice("Within loose route\n"); + if(!isdsturiset()) { + handle_ruri_alias(); + #if ($rc == 1) { + # $ru = "sip:" + $rU + "@" + $dd + ":" + $dp + ";transport=" + $rP; + #} + } + + if ($route_uri =~ "sip:mt@.*") { + route(MT_indialog); + } else { + route(MO_indialog); + } + + # Handle NAT + route(NATMANAGE); + + route(RELAY); + exit; + } + if ( is_method("ACK") ) { + xlog("Contact of Reply: $T_rpl($ct)\n"); + if ( t_check_trans() ) { + # no loose-route, but stateful ACK; + # must be an ACK after a 487 + # or e.g. 404 from upstream server + t_relay(); + exit; + } else { + # ACK without matching transaction ... ignore and discard + exit; + } + } + sl_send_reply("404","Not here"); + exit; + } +} + +###################################################################### +# Negative replies to REGISTER requests: +###################################################################### +failure_route[SBC_failure] { +#!ifdef WITH_IPBLOCK + if (is_method("REGISTER") && !ds_is_from_list()) { + if (t_check_status("403|[5-6][0-9][0-9]")) { + if ($sht(failedauth=>$si) != $null) + $sht(failedauth=>$si) = $sht(failedauth=>$si) + 1; + else + $sht(failedauth=>$si) = 1; + if ($sht(failedauth=>$si) > 10) { + xlog("L_ALERT","ALERT: blocking $rm from $fu (IP:$si:$sp), more than 5 failed auth requests!\n"); + xlog("Blocking traffic from $si\n"); + $sht(ipban=>$si) = 1; + } + } + } +#!endif + # Choose another gateway, in case we + # - get a local generated "408" + # - receive a 5xx or 6xx reply from the proxy. + if (t_branch_timeout() || t_check_status("[5-6]..")) { + if (ds_next_dst()) { + # Do Failover in case problems: + t_on_failure("SBC_failure"); + t_relay(); + } else { + # Add a header, to indicate the phone should try again in 30 seconds. + append_hf("Retry-After: 30\r\n"); + send_reply("504", "Server Time-Out"); + } + exit; + } +} + +# Notify Route: # +##################################################################### +route[NOTIFY] +{ + xlog("L_DBG", "IMS: INSIDE NOTIFY\n"); + if (reginfo_handle_notify("pcscf_location")) { + send_reply("200","OK - P-CSCF processed notification"); + break; + } else { + t_reply("500","Error encountered while processing notification"); + break; + } +} + +#!ifdef WITH_NATPING +# NATPING Route: # +##################################################################### +route[NATPING] { + route(preload_pcscf); + + sht_lock("natping=>natpinglock"); + sht_iterator_start("nat_iterator", "natping"); + while(sht_iterator_next("nat_iterator")) { + xnotice("OPTIONS to $shtitval(nat_iterator) via $shtitkey(nat_iterator)...\n"); + $uac_req(method) = "OPTIONS"; + $uac_req(ruri) = $shtitval(nat_iterator); + $uac_req(furi) = PCSCF_URL; + $uac_req(sock) = $sht(natpingfrom=>$shtitkey(nat_iterator)); + $uac_req(turi) = $shtitval(nat_iterator); + $uac_req(ouri) = $shtitkey(nat_iterator); + $uac_req(evroute) = 1; + uac_req_send(); + } + sht_iterator_end("nat_iterator"); + sht_unlock("natping=>natpinglock"); +} + +event_route[uac:reply] { +##!ifdef WITH_DEBUG + xnotice("request sent to $uac_req(ruri) completed with code: $uac_req(evcode), Type $uac_req(evtype)\n"); +##!endif + if (($uac_req(evtype) != 1) || ($uac_req(evcode) != 200)) { + if ($sht(natpingfail=>$uac_req(ouri)) == $null) { + $sht(natpingfail=>$uac_req(ouri)) = 1; + } else { + $sht(natpingfail=>$uac_req(ouri)) = $sht(natpingfail=>$uac_req(ouri)) + 1; + } + xlog(" request sent to $uac_req(ruri): Fail Counter is $sht(natpingfail=>$uac_req(ouri))\n"); + if ($sht(natpingfail=>$uac_req(ouri)) > 10) { + if ($(uac_req(ouri){uri.transport}) == "tcp") { + $var(alias) = "alias="+$(uac_req(ouri){uri.host})+"~"+$(uac_req(ouri){uri.port})+"~2"; + } else if ($(uac_req(ouri){uri.transport}) == "tls") { + $var(alias) = "alias="+$(uac_req(ouri){uri.host})+"~"+$(uac_req(ouri){uri.port})+"~3"; + } else { + $var(alias) = "alias="+$(uac_req(ouri){uri.host})+"~"+$(uac_req(ouri){uri.port})+"~1"; + } + xlog(" Unregistering $uac_req(ruri);$var(alias)\n"); + setdebug("9"); +#!ifdef WITH_IPSEC + ipsec_destroy_by_contact("pcscf_location", "$uac_req(ruri);$var(alias)", "$(uac_req(ouri){uri.host})", "$(uac_req(ouri){uri.port})"); +#!endif + pcscf_unregister("pcscf_location", "$uac_req(ruri);$var(alias)", "$(uac_req(ouri){uri.host})", "$(uac_req(ouri){uri.port})"); + resetdebug(); + sht_lock("natping=>natpinglock"); + $sht(natping=>$uac_req(ouri)) = $null; + sht_unlock("natping=>natpinglock"); + $sht(natpingfail=>$uac_req(ouri)) = $null; + + sht_lock("natpingfrom=>natpingfromlock"); + $sht(natpingfrom=>$uac_req(ouri)) = $null; + sht_unlock("natpingfrom=>natpingfromlock"); + $sht(natpingfail=>$uac_req(ouri)) = $null; + } + } else { + $sht(natpingfail=>$uac_req(ouri)) = $null; + } +} + +event_route[htable:expired:natping] { + xlog("natping record expired $shtrecord(key) => $shtrecord(value)\n"); +} + +event_route[htable:mod-init] { + xlog("event_route[htable:mod-init] \n"); +} + +route[preload_pcscf] { + if ($shv(preload_pcscf) == 1) return; + $shv(preload_pcscf) = 1; + + sql_query("pcscf", "select aor, received, received_port, received_proto from pcscf_location;", "resultset"); + xlog("L_INFO", "Preloading NAT-PING. Rows: $dbr(resultset=>rows)\n"); + if($dbr(resultset=>rows)>0) { + $var(i) = 0; + while($var(i) < $dbr(resultset=>rows)) { + $var(ouri) = "sip:"+$dbr(resultset=>[$var(i),1])+":"+$dbr(resultset=>[$var(i),2]); + if ($dbr(resultset=>[$var(i),3]) == 2) { + $var(ouri) = $var(ouri)+";transport=tcp"; + } else if ($dbr(resultset=>[$var(i),3]) == 3) { + $var(ouri) = $var(ouri)+";transport=tls"; + } + $var(noalias) = $(dbr(resultset=>[$var(i),0]){re.subst,/^(.*);alias=.*/\1/}{nameaddr.uri}); + # xlog("$$var(noalias) => $var(noalias) (via $var(ouri))\n"); + sht_lock("natping=>natpinglock"); + $sht(natping=>$var(ouri)) = $var(noalias); + sht_unlock("natping=>natpinglock"); + $var(i) = $var(i) + 1; + } + } + sql_result_free("resultset"); +} +#!endif + +#!ifdef WITH_N5 + +# 5G N5 HTTP2 Server routing script basic code +event_route[nghttp2:request] { + xinfo("request: $nghttp2(method) - url: $nghttp2(path) - data: [$nghttp2(data)]\n"); + + # Check if the requested URL is /nf-status-notify + if ($nghttp2(path) == "/nf-status-notify") { + nghttp2_reply_header("Content-Type", "text/html"); + nghttp2_reply_header("Server:", "AF"); + nghttp2_reply("200", "PCF registered at PCSCF"); + } else if ($nghttp2(path) == "/terminate") { + nghttp2_reply_header("accept", "application/json"); + nghttp2_reply_header("accept", "application/problem+json"); + nghttp2_reply_header("Content-Type", "application/json"); + nghttp2_reply_header("Server", "AF"); + nghttp2_reply("204", "No Content"); + } else { + # Optionally handle other URLs or do nothing + nghttp2_reply_header("accept", "application/json"); + nghttp2_reply_header("accept", "application/problem+json"); + nghttp2_reply_header("Content-Type", "application/json"); + nghttp2_reply_header("Server", "AF"); + nghttp2_reply("404", "Not Found"); + } +} + +route[NRF_NFM] { + if ($var(n5_hb_fail_count) > 5) { + xlog("L_ERR", "PCSCF NF no longer registered at SCP. Re-attempting registration!!\n"); + $var(n5_initalized) = 0; + } + + $var(time_now) = $_s($timef(%a, %d %b %Y %H:%M:%S %Z)); + + # TODO: Send at heartbeat intervals received in reponse to NF registration + if ($var(n5_initalized) == 1) { + # Send Heartbeat + $var(nf_hb_headers) = "content-type: application/json-patch+json\r\n"; + $var(nf_hb_headers) = $var(nf_hb_headers) + "accept: application/json,application/problem+json\r\n"; + $var(nf_hb_headers) = $var(nf_hb_headers) + "3gpp-sbi-discovery-target-nf-type: NRF\r\n"; + $var(nf_hb_headers) = $var(nf_hb_headers) + "3gpp-sbi-max-rsp-time: 10000\r\n"; + $var(nf_hb_headers) = $var(nf_hb_headers) + "3gpp-sbi-discovery-service-names: nnrf-nfm\r\n"; + $var(nf_hb_headers) = $var(nf_hb_headers) + "3gpp-sbi-sender-timestamp: " + $var(time_now); + + $var(nf_hb_json_body) ='[]'; + $var(nf_hb_body) = '{ + "op": "replace", + "path": "/nfStatus", + "value": "REGISTERED" + }'; + jansson_append("obj", "", $var(nf_hb_body), "$var(nf_hb_json_body)"); + $var(nf_hb_body) = '{ + "op": "replace", + "path": "/load", + "value": 0 + }'; + jansson_append("obj", "", $var(nf_hb_body), "$var(nf_hb_json_body)"); + + http_client_request_v2pk("PATCH", "http://SCP_BIND_IP:SCP_BIND_PORT/nnrf-nfm/v1/nf-instances/$var(pcscf_uuid)", "$var(nf_hb_json_body)", "$var(nf_hb_headers)", "$var(nf_hb_result)"); + switch ($rc) { + case 204: + $var(n5_hb_fail_count) = 0; + break; + default: + $var(n5_hb_fail_count) = $var(n5_hb_fail_count) + 1; + return; + } + return; + } + + # Generate UUID for PCSCF + $var(pcscf_uuid) = $uuid(g); + + # Register NF + $var(nf_reg_headers) = "content-type: application/json\r\n"; + $var(nf_reg_headers) = $var(nf_reg_headers) + "accept: application/json,application/problem+json\r\n"; + $var(nf_reg_headers) = $var(nf_reg_headers) + "3gpp-sbi-discovery-target-nf-type: NRF\r\n"; + $var(nf_reg_headers) = $var(nf_reg_headers) + "3gpp-sbi-max-rsp-time: 10000\r\n"; + $var(nf_reg_headers) = $var(nf_reg_headers) + "3gpp-sbi-discovery-service-names: nnrf-nfm\r\n"; + $var(nf_reg_headers) = $var(nf_reg_headers) + "3gpp-sbi-sender-timestamp: " + $var(time_now); + + $var(nf_reg_body) = '{ + "nfInstanceId": "PCSCF_UUID", + "nfType": "AF", + "nfStatus": "REGISTERED", + "ipv4Addresses": ["N5_BIND_IP"], + "allowedNfTypes": ["SCP", "PCF"], + "priority": 0, + "capacity": 100, + "load": 0, + "nfServiceList": { + "PCSCF_UUID": { + "serviceInstanceId": "PCSCF_UUID", + "serviceName": "npcf-policyauthorization", + "versions": [ + { + "apiVersionInUri": "v2", + "apiFullVersion": "2.0.0" + } + ], + "scheme": "http", + "nfServiceStatus": "REGISTERED", + "ipEndPoints": [ + { + "ipv4Address": "N5_BIND_IP", + "port": N5_BIND_PORT + } + ], + "allowedNfTypes": [ + "PCF" + ], + "priority": 0, + "capacity": 100, + "load": 0 + } + }, + "nfProfileChangesSupportInd": true + }'; + $var(nf_reg_body) = $(var(nf_reg_body){re.subst,/PCSCF_UUID/$var(pcscf_uuid)/g}); + jansson_append("obj", "", "$var(nf_reg_body)", "$var(nf_reg_json_body)"); + + http_client_request_v2pk("PUT", "http://SCP_BIND_IP:SCP_BIND_PORT/nnrf-nfm/v1/nf-instances/$var(pcscf_uuid)", "$var(nf_reg_json_body)", "$var(nf_reg_headers)", "$var(nf_reg_result)"); + switch ($rc) { + case 201: + xlog("L_INFO", "P-CSCF NF registered successfully at SCP\n"); + $var(n5_initalized) = 1; + $var(n5_hb_fail_count) = 0; + route(NRF_NFM_SUBSCRIBE_PCF); + break; + default: + xlog("L_ERR", "P-CSCF NF failed to register at SCP with code=$rc\n"); + return; + } +} + +route[NRF_NFM_SUBSCRIBE_PCF] { + # Subscribe to PCF NF registration notification + $var(time_now) = $_s($timef(%a, %d %b %Y %H:%M:%S %Z)); + $var(pcf_subc_headers) = "content-type: application/json\r\n"; + $var(pcf_subc_headers) = $var(pcf_subc_headers) + "accept: application/json,application/problem+json\r\n"; + $var(pcf_subc_headers) = $var(pcf_subc_headers) + "3gpp-sbi-discovery-target-nf-type: NRF\r\n"; + $var(pcf_subc_headers) = $var(pcf_subc_headers) + "3gpp-sbi-callback: Nnrf_NFManagement_NFStatusNotify\r\n"; + $var(pcf_subc_headers) = $var(pcf_subc_headers) + "3gpp-sbi-max-rsp-time: 10000\r\n"; + $var(pcf_subc_headers) = $var(pcf_subc_headers) + "3gpp-sbi-discovery-service-names: nnrf-nfm\r\n"; + $var(pcf_subc_headers) = $var(pcf_subc_headers) + "3gpp-sbi-sender-timestamp: " + $var(time_now); + + $var(pcf_subc_body) = '{ + "nfStatusNotificationUri": "http://N5_BIND_IP:N5_BIND_PORT/nnrf-nfm/v1/nf-status-notify", + "reqNfInstanceId": "PCSCF_UUID", + "subscrCond": { + "nfType": "PCF" + }, + "reqNfType": "AF", + "requesterFeatures": "1" + }'; + $var(pcf_subc_body) = $(var(pcf_subc_body){re.subst,/PCSCF_UUID/$var(pcscf_uuid)/g}); + jansson_append("obj", "", "$var(pcf_subc_body)", "$var(pcf_subc_json_body)"); + + http_client_request_v2pk("POST", "http://SCP_BIND_IP:SCP_BIND_PORT/nnrf-nfm/v1/subscriptions", "$var(pcf_subc_json_body)", "$var(pcf_subc_headers)", "$var(pcf_subc_result)"); + switch ($rc) { + case 201: + xlog("L_INFO", "P-CSCF NF subscribed for PCF NF registration notification\n"); + break; + default: + xlog("L_ERR", "P-CSCF NF failed to subscribe for PCF NF registration notification\n"); + return; + } +} +#!endif + +#!ifdef WITH_XMLRPC +include_file "route/xmlrpc.cfg" +#!endif +#!ifdef WITH_WEBSOCKET +include_file "route/websocket.cfg" +#!endif +include_file "route/register.cfg" +include_file "route/rtp.cfg" +include_file "route/mo.cfg" +include_file "route/mt.cfg" diff --git a/pcscf/pcscf.cfg b/pcscf/pcscf.cfg new file mode 100644 index 0000000..7a99d00 --- /dev/null +++ b/pcscf/pcscf.cfg @@ -0,0 +1,152 @@ +# IP-Adress for incoming SIP-Traffic, in the following format: + +# SIP / UDP +listen=udp:PCSCF_IP:5060 +#listen=udp:PCSCF_IP:5060 advertise PCSCF_PUB_IP:5060 +# SIP / TCP +listen=tcp:PCSCF_IP:5060 +#listen=tcp:PCSCF_IP:5060 advertise PCSCF_PUB_IP:5060 +# SIP / TCP/TLS +#listen=tls:PCSCF_IP:5061 + +# IPSEC / UDP +#!define IPSEC_LISTEN_ADDR "PCSCF_IP" +##!define IPSEC_LISTEN_ADDR "PCSCF_PUB_IP" +#!define IPSEC_CLIENT_PORT 5100 +#!define IPSEC_SERVER_PORT 6100 +#!define IPSEC_MAX_CONN 10 + +# Value: 1 for true and 0 for false +#!define IPSEC_DELETE_UNUSED_TUNNELS 1 + +# Delay in seconds to delete contact from registrar +#!define CONTACT_DELETE_DELAY 10 + +# Logical OR of following flags: +# - IPSEC_SEND_FORCE_SOCKET 1 +# - IPSEC_SETDSTURI_FULL 128 +# - IPSEC_FORWARD_USEVIA 256 +# - IPSEC_FORWARD_TRYTCP 512 +#!define IPSEC_FORWARD_FLAGS 897 + +#!define RX_IMS_REG_DIALOG_DIRECTION 3 + +# IP used in Rx_AAR_Register - IP of this P-CSCF, to be used in the flow for the AF-signaling +#!define RX_AF_SIGNALING_IP "PCSCF_IP" +# Uncomment the below line only when UE is behind double NAT (e.g. VoIP calling over WiFi/ CN behind a NAT) +##!define RX_AF_SIGNALING_IP "PCSCF_PUB_IP" + + +# IP and Port for incoming requests over N5 from 5G Core +#!substdef "/N5_BIND_IP/PCSCF_IP/g" +#!substdef "/N5_BIND_PORT/7777/g" + +# SCP IP and Port for NF registration and heartbeat +#!substdef "/SCP_BIND_IP/SCP_IP/g" +#!substdef "/SCP_BIND_PORT/7777/g" + +alias=pcscf.IMS_DOMAIN + +#!define MY_WS_PORT 80 +#!define MY_WSS_PORT 443 + +#!define PCSCF_URL "sip:pcscf.IMS_DOMAIN:5060" + +#!define TCP_PROCESSES 8 + +# Maximum lifetime of a subscription in seconds (same is advertised to UE) +#!substdef "/UE_SUBSCRIPTION_EXPIRES/SUBSCRIPTION_EXPIRES_ENV/g" + +#!subst "/NETWORKNAME/IMS_DOMAIN/g" +#!subst "/HOSTNAME/pcscf.IMS_DOMAIN/g" +#!subst "/PCRF_REALM/EPC_DOMAIN/g" + +# SIP-Address of capturing node, if not set, capturing is disabled. +##!define CAPTURE_NODE "sip:127.0.0.1:9060" + +# Allowed IPs for XML-RPC-Queries +##!define XMLRPC_WHITELIST_1 "127.0.0.1" +##!define XMLRPC_WHITELIST_2 "127.0.0.1" +##!define XMLRPC_WHITELIST_3 "127.0.0.1" + +# Databases: +#!define DB_URL "mysql://pcscf:heslo@MYSQL_IP/pcscf" +##!define DB_URL2 "con2=>mysql://pcscf:heslo@MYSQL_IP/pcscf" + +#!define SQLOPS_DBURL "pcscf=>mysql://pcscf:heslo@MYSQL_IP/pcscf" + +#! Optional: Server-URL for Websocket-Requests +##!define WEBSOCKET_WEBSERVER "phone.ng-voice.com" + +##!define TRF_FUNCTION "trf.IMS_DOMAIN" + +# +# Several features can be enabled using '#!define WITH_FEATURE' directives: +# +# *** To run in debug mode: +# - define WITH_DEBUG +# +# *** To enable nat traversal execute: +# - define WITH_NAT +# - define the connection to the RTP-Proxy: RTPPROXY_ADDRESS +# +# *** To force alls calls through the RTP-Proxy +# - this will automagically enable NAT-Traversal +# - define FORCE_RTPRELAY +# +# *** To enable IPv4/IPv6 Translation (RTPProxy) +# - this will automagically enable NAT-Traversal +# - define WITH_RTPIPV4 +# +# *** To enable TCP support execute: +# - define WITH_TCP +# +# *** To enable TLS support execute: +# - adjust CFGDIR/tls.cfg as needed +# - define WITH_TLS +# - this will automagically enable TCP +# +# *** To enable XMLRPC support execute: +# - define WITH_XMLRPC +# - this will automagically enable TCP +# +# *** To enable anti-flood detection execute: +# - adjust pike and htable=>ipban settings as needed (default is +# block if more than 16 requests in 2 seconds and ban for 300 seconds) +# - define WITH_ANTIFLOOD +# +# *** To enable the Rx-Interface: +# - Configure Rx-Diameter-Interface in pcscf.xml +# - define WITH_RX +# +# *** To enable a Homer SIP-Capter-Node: +# - define CAPTURE_NODE with a proper address +# +# *** To enable support for the SEMS-SBC +# - define WITH_SBC +# - configure dispatcher-list with a set of SBC's + +# +# Enabled Features for this host: +##!define WITH_DEBUG +##!define WITH_DEBUG_TRACE +#!define WITH_NAT +##!define WITH_NATPING +#!define FORCE_RTPRELAY +##!define WITH_TLS +##!define WITH_XMLRPC +##!define WITH_IPBLOCK +##!define WITH_ANTIFLOOD +#!define WITH_RX +##!define WITH_N5 +#!define WITH_TCP +##!define WITH_RTPIPV4 +##!define WITH_SBC +##!define WITH_SBC_CALL +##!define WITH_REGINFO +##!define WITH_RTPPING +##!define WITH_WEBSOCKET +#!define WITH_IPSEC +#!define WITH_IMS_HDR_CACHE +#!define WITH_PING_UDP +#!define WITH_PING_TCP diff --git a/pcscf/pcscf.xml b/pcscf/pcscf.xml new file mode 100644 index 0000000..9abbd4c --- /dev/null +++ b/pcscf/pcscf.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/pcscf/pcscf_init.sh b/pcscf/pcscf_init.sh new file mode 100755 index 0000000..53a6786 --- /dev/null +++ b/pcscf/pcscf_init.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +# BSD 2-Clause License + +# Copyright (c) 2020, Supreeth Herle +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +sh -c "echo 1 > /proc/sys/net/ipv4/ip_nonlocal_bind" +sh -c "echo 1 > /proc/sys/net/ipv6/ip_nonlocal_bind" + +[ ${#MNC} == 3 ] && EPC_DOMAIN="epc.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || EPC_DOMAIN="epc.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" +[ ${#MNC} == 3 ] && IMS_DOMAIN="ims.mnc${MNC}.mcc${MCC}.3gppnetwork.org" || IMS_DOMAIN="ims.mnc0${MNC}.mcc${MCC}.3gppnetwork.org" + +mkdir -p /etc/kamailio_pcscf +cp /mnt/pcscf/pcscf.cfg /etc/kamailio_pcscf +cp /mnt/pcscf/pcscf.xml /etc/kamailio_pcscf +cp /mnt/pcscf/kamailio_pcscf.cfg /etc/kamailio_pcscf +cp -r /mnt/pcscf/route /etc/kamailio_pcscf +cp -r /mnt/pcscf/sems /etc/kamailio_pcscf +cp /mnt/pcscf/tls.cfg /etc/kamailio_pcscf +cp /mnt/pcscf/dispatcher.list /etc/kamailio_pcscf + +while ! mysqladmin ping -h ${MYSQL_IP} --silent; do + sleep 5; +done + +# Sleep until permissions are set +sleep 10; + +# Create PCSCF database, populate tables and grant privileges +if [[ -z "`mysql -u root -h ${MYSQL_IP} -qfsBe "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='pcscf'" 2>&1`" ]]; +then + mysql -u root -h ${MYSQL_IP} -e "create database pcscf;" + mysql -u root -h ${MYSQL_IP} pcscf < /usr/local/src/kamailio/utils/kamctl/mysql/standard-create.sql + mysql -u root -h ${MYSQL_IP} pcscf < /usr/local/src/kamailio/utils/kamctl/mysql/presence-create.sql + mysql -u root -h ${MYSQL_IP} pcscf < /usr/local/src/kamailio/utils/kamctl/mysql/ims_usrloc_pcscf-create.sql + mysql -u root -h ${MYSQL_IP} pcscf < /usr/local/src/kamailio/utils/kamctl/mysql/ims_dialog-create.sql + PCSCF_USER_EXISTS=`mysql -u root -h ${MYSQL_IP} -s -N -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE User = 'pcscf' AND Host = '%')"` + if [[ "$PCSCF_USER_EXISTS" == 0 ]] + then + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'pcscf'@'%' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'pcscf'@'$PCSCF_IP' IDENTIFIED WITH mysql_native_password BY 'heslo'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON pcscf.* TO 'pcscf'@'%'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON pcscf.* TO 'pcscf'@'$PCSCF_IP'"; + mysql -u root -h ${MYSQL_IP} -e "FLUSH PRIVILEGES;" + fi +fi + +if [[ ${DEPLOY_MODE} == 5G ]]; +then + sed -i 's|#!define WITH_RX\b|##!define WITH_RX|g' /etc/kamailio_pcscf/pcscf.cfg + sed -i 's|##!define WITH_N5\b|#!define WITH_N5|g' /etc/kamailio_pcscf/pcscf.cfg +fi + +SUBSCRIPTION_EXPIRES_ENV=3600 + +sed -i 's|PCSCF_IP|'$PCSCF_IP'|g' /etc/kamailio_pcscf/pcscf.cfg +sed -i 's|SUBSCRIPTION_EXPIRES_ENV|'$SUBSCRIPTION_EXPIRES_ENV'|g' /etc/kamailio_pcscf/pcscf.cfg +sed -i 's|SCP_IP|'$SCP_IP'|g' /etc/kamailio_pcscf/pcscf.cfg +sed -i 's|PCSCF_PUB_IP|'$PCSCF_PUB_IP'|g' /etc/kamailio_pcscf/pcscf.cfg +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/kamailio_pcscf/pcscf.cfg +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/kamailio_pcscf/pcscf.cfg +sed -i 's|MYSQL_IP|'$MYSQL_IP'|g' /etc/kamailio_pcscf/pcscf.cfg + +sed -i 's|PCSCF_IP|'$PCSCF_IP'|g' /etc/kamailio_pcscf/pcscf.xml +sed -i 's|SUBSCRIPTION_EXPIRES_ENV|'$SUBSCRIPTION_EXPIRES_ENV'|g' /etc/kamailio_pcscf/pcscf.xml +sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/kamailio_pcscf/pcscf.xml +sed -i 's|EPC_DOMAIN|'$EPC_DOMAIN'|g' /etc/kamailio_pcscf/pcscf.xml +sed -i 's|PCRF_BIND_PORT|'$PCRF_BIND_PORT'|g' /etc/kamailio_pcscf/pcscf.xml +sed -i 's|PCSCF_BIND_PORT|'$PCSCF_BIND_PORT'|g' /etc/kamailio_pcscf/pcscf.xml + +sed -i 's|RTPENGINE_IP|'$RTPENGINE_IP'|g' /etc/kamailio_pcscf/kamailio_pcscf.cfg + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# Add static route to route traffic back to UE as there is not NATing +ip r add ${UE_IPV4_IMS} via ${UPF_IP} diff --git a/pcscf/route/mo.cfg b/pcscf/route/mo.cfg new file mode 100644 index 0000000..fd4ebad --- /dev/null +++ b/pcscf/route/mo.cfg @@ -0,0 +1,680 @@ +###################################################################### +# Originating, Intial Requests +###################################################################### +route[MO] +{ + # Strip Transport from RURI: + $ru = $(ru{re.subst,/;transport=[A-Za-z]*//g}); + xnotice("PCSCF MO: \n Destination URI: $du\n Request URI: $ru\n"); + xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n"); + xnotice("Received IP and Port: ($Ri:$Rp)\n"); + xnotice("Next hop domain: ($nh(d))\n"); + xnotice("Contact header: $ct\n"); + + # Process route headers, if any: + loose_route(); + if (!pcscf_is_registered("pcscf_location")) { + send_reply("403","Forbidden - You must register first with a S-CSCF"); + exit; + } + + # We do not trust the user, let's remove the P-Asserted-Identity, if any: + remove_hf("P-Asserted-Identity"); + remove_hf("P-Preferred-Identity"); + + # Add P-Charging-Vector + sip_p_charging_vector("g"); + + if (is_present_hf("P-Preferred-Identity") && pcscf_assert_identity("pcscf_location", "$hdr(P-Preferred-Identity)") && $hdr(P-Preferred-Identity) =~ "sip:.*") { + append_hf("P-Asserted-Identity: $hdr(P-Preferred-Identity)\r\n"); + } else if (is_present_hf("P-Asserted-Identity") && pcscf_assert_identity("pcscf_location", "$hdr(P-Asserted-Identity)") && $hdr(P-Asserted-Identity) =~ "sip:.*") { + append_hf("P-Asserted-Identity: $hdr(P-Asserted-Identity)\r\n"); + } else if (pcscf_assert_identity("pcscf_location", "$(fu{tobody.uri})")) { + # For broken SIP implementation in Samsung devices + if ($fu =~ "tel:.*") { + $var(new_hdr) = $(fu{tobody.uri}) + "@NETWORKNAME"; + $var(new_hdr) = $(var(new_hdr){re.subst,/tel:/sip:/g}); + append_hf("P-Asserted-Identity: <$var(new_hdr)>\r\n"); + $fu = $var(new_hdr); + } else { + append_hf("P-Asserted-Identity: <$(fu{tobody.uri})>\r\n"); + } + } else { + append_hf("P-Asserted-Identity: <$pcscf_asserted_identity>\r\n"); + } + + if (!pcscf_follows_service_routes("pcscf_location")){ + #Variant 1 - deny access to the network + #send_reply("400","Bad Request - Not following indicated service routes"); + #break; + + #Variant 2 - enforce routes and let the dialog continue + pcscf_force_service_routes("pcscf_location"); + } + + # add IBCF/THIG route here if required + # Check for "sec-agree" in the Require header: + if (is_present_hf("Require") && $hdr(Require) =~ ".*sec-agree.*") { + # Remove the old Require-Header: + remove_hf("Require"); + # Replace ", sec-agree" with "" + $var(new_hdr) = $(hdr(Require){re.subst,/[, ]*sec-agree//gi}); + if ($(var(new_hdr){s.len}) > 0) { + append_hf("Require: $var(new_hdr)\r\n"); + } + } + + # Check for "sec-agree" in the Proxy-Require header: + if (is_present_hf("Proxy-Require") && $hdr(Proxy-Require) =~ ".*sec-agree.*") { + # Remove the old Proxy-Require-Header: + remove_hf("Proxy-Require"); + # Replace ", sec-agree" with "" + $var(new_hdr) = $(hdr(Proxy-Require){re.subst,/[, ]*sec-agree//gi}); + if ($(var(new_hdr){s.len}) > 0) { + append_hf("Proxy-Require: $var(new_hdr)\r\n"); + } + } + remove_hf("Security-Verify"); + +#!ifdef WITH_N5 + if(is_method("INVITE")) { + route(N5_INIT_REQ); + } +#!endif + +#!ifdef TRF_FUNCTION + $var(trf) = TRF_FUNCTION; + # Check for "sec-agree" in the Proxy-Require header: + if (is_present_hf("Feature-Caps")) { + # Remove the old Proxy-Require-Header: + remove_hf("Feature-Caps"); + append_hf("Feature-Caps: $hdr(Feature-Caps);+g.3gpp.trf=\"\"\r\n"); + } else { + append_hf("Feature-Caps: *;+g.3gpp.trf=\"\"\r\n"); + } +#!endif + # Add a visited Network-ID-Header: + if (is_present_hf("P-Visited-Network-ID")) { + $var(new_hdr) = "NETWORKNAME, "+$hdr(P-Visited-Network-ID); + append_hf("P-Visited-Network-ID: $var(new_hdr)\r\n"); + } else { + append_hf("P-Visited-Network-ID: NETWORKNAME\r\n"); + } + set_dlg_profile("orig"); + t_on_reply("MO_reply"); +} + +#!ifdef WITH_N5 + +# Route Logic for N5 Requests +route[N5_INIT_REQ] { + + # Storing IDs and IPs of UE into variables to use them later in the N5 Request + $var(orig_ue_ip) = $si; + $var(orig_ue_port) = $sp; + $var(pcscf_ip) = $Ri; + $var(pcscf_port) = $Rp; + + xlog("L_INFO", "Connection Info for UE $var(orig_ue_ip) $var(orig_ue_port)\n"); + xlog("L_INFO", "Connection Info for P-CSCF is: $var(pcscf_ip) $var(pcscf_port)\n"); + + $var(user_id_req_ip) = $fU; + # Store the IP in the hash table associated with the UE + $sht(user_sip_ips=>$var(user_id_req_ip)) = $var(orig_ue_ip); + xlog("L_INFO", "IP Info for UE MSISDN $var(user_id_req_ip): $var(orig_ue_ip)\n"); + + $var(user_id_req_port) = $fU; + # Store the Port in the hash table associated with the UE + $sht(user_sip_ports=>$var(user_id_req_port)) = $var(orig_ue_port); + xlog("L_INFO", "Port Info for UE MSISDN $var(user_id_req_port): $var(orig_ue_port)\n"); + + # Storing SDP Info of UE to variables to use them later in the N5 Flow Fdecs + $var(sdp_src_ip) = $sdp(c:ip); + $var(sdp_src_port) = $sdp(m0:rtp:port); + $var(sdp_src_rtcp_port) = $sdp(m0:rtcp:port); + $var(sdp_mline_raw) = $sdp(m0:raw); + + xlog("L_INFO", "SDP Info : Connection IP is $var(sdp_src_ip) Port is $var(sdp_src_port) Mline dump $var(sdp_mline_raw) \n"); + + $var(user_id_sdp_ip) = $fU; + # Store the SDP source IP in the hash table associated with the UE + $sht(user_sdps_ip=>$var(user_id_sdp_ip)) = $var(sdp_src_ip); + xlog("L_INFO", "SDP source IP of Orig UE $var(user_id_sdp_ip): $var(sdp_src_ip)\n"); + + $var(user_id_sdp_port) = $fU; + # Store the SDP Media_Port in the hash table associated with the UE + $sht(user_sdps_port=>$var(user_id_sdp_port)) = $var(sdp_src_port); + xlog("L_INFO", "SDP Media Port of Orig UE $var(user_id_sdp_port): $var(sdp_src_port)\n"); + + $var(user_id_sdp_rtcp_port) = $fU; + # Store the RTCP Media Port in the hash table associated with the UE + $sht(user_sdps_rtcp_port=>$var(user_id_sdp_rtcp_port)) = $var(sdp_src_rtcp_port); + xlog("L_INFO", "SDP RTCP Media Port of Orig UE $var(user_id_sdp_rtcp_port): $var(sdp_src_rtcp_port)\n"); + + # 5G VoNR N5 NPCF Authorization request + xlog("L_DBG", "IMS: INVITE ORIG TO $tU\n"); + + # Retrieve the IP/Port of UE + $var(orig_ue_ip) = $fU; + $var(ue_ip_addr) = $sht(user_sip_ips=>$var(orig_ue_ip)); + xlog("L_INFO", "IP for UE $var(orig_ue_ip) is: $var(ue_ip_addr)\n"); + + $var(orig_ue_port) = $fU; + $var(ue_port_sip) = $sht(user_sip_ports=>$var(orig_ue_port)); + xlog("L_INFO", "IP for UE $var(orig_ue_port) is: $var(ue_port_sip)\n"); + + # Retrieving SDP Connection Info and Media Port for UE + $var(sdp_id_ue) = $fU; + $var(ue_sdp_ip) = $sht(user_sdps_ip=>$var(sdp_id_ue)); + xlog("L_INFO", "SDP IP for UE with MSISDN $var(sdp_id_ue) is: $var(ue_sdp_ip)\n"); + + $var(sdp_id_ue_port) = $fU; + $var(ue_sdp_port) = $sht(user_sdps_port=>$var(sdp_id_ue_port)); + xlog("L_INFO", "SDP Port for UE with MSISDN $var(sdp_id_ue_port) is: $var(ue_sdp_port)\n"); + + + $var(sdp_id_ue_rtcp_port) = $fU; + $var(ue_sdp_rtcp_port) = $sht(user_sdps_rtcp_port=>$var(sdp_id_ue_rtcp_port)); + xlog("L_INFO", "SDP Port for UE with MSISDN $var(sdp_id_ue_rtcp_port) is: $var(ue_sdp_rtcp_port)\n"); + + # Build the N5 Request + xlog("L_INFO","Preparing QoS N5 Message to PCF for the INVITE\n"); + + $var(events) = '[]'; + $var(medComponents) = '{}'; + $var(medSubComps) = '{}'; + $var(evSubsc) = '{}'; + $var(payload) = '{}'; + + # Set afAppId and dnn in payload + jansson_set("string", "afAppId", "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel\"", "$var(payload)"); # adding a note that this could be improved in future to get the value SIP Header + jansson_set("string", "dnn", "ims", "$var(payload)"); + + # Set medComponents + jansson_set("integer", "medCompN", 1, "$var(medComp)"); + jansson_set("string", "qosReference", "qosVoNR", "$var(medComp)"); + jansson_set("string", "medType", "AUDIO", "$var(medComp)"); + jansson_set("array", "codecs", "[\"downlink\\noffer\\n\", \"uplink\\nanswer\\n\"]", "$var(medComp)"); + + # RTP + jansson_set("integer", "fNum", 1, "$var(medSubComp1)"); + jansson_set("array", "fDescs", "[\"permit out 17 from any to $var(ue_sdp_ip) $var(ue_sdp_port)\", \"permit in 17 from $var(ue_sdp_ip) $var(ue_sdp_port) to any\"]", "$var(medSubComp1)"); + jansson_set("string", "fStatus", "ENABLED", "$var(medSubComp1)"); + jansson_set("string", "marBwDl", "5000 Kbps", "$var(medSubComp1)"); + jansson_set("string", "marBwUl", "3000 Kbps", "$var(medSubComp1)"); + jansson_set("string", "flowUsage", "NO_INFO", "$var(medSubComp1)"); + + + # RTCP + jansson_set("integer", "fNum", 2, "$var(medSubComp2)"); + jansson_set("array", "fDescs", "[\"permit out 17 from any to $var(ue_sdp_ip) $var(ue_sdp_rtcp_port)\", \"permit in 17 from $var(ue_sdp_ip) $var(ue_sdp_rtcp_port) to any\"]", "$var(medSubComp2)"); + jansson_set("string", "fStatus", "ENABLED", "$var(medSubComp2)"); + jansson_set("string", "marBwDl", "5000 Kbps", "$var(medSubComp2)"); + jansson_set("string", "marBwUl", "3000 Kbps", "$var(medSubComp2)"); + jansson_set("string", "flowUsage", "RTCP", "$var(medSubComp2)"); + + # Merging the flows under MediaSubComponent + jansson_set("obj", "0", "$var(medSubComp1)", "$var(medSubComps)"); + jansson_set("obj", "1", "$var(medSubComp2)", "$var(medSubComps)"); + jansson_set("obj", "medSubComps", "$var(medSubComps)", "$var(medComp)"); + + jansson_set("obj", "0", "$var(medComp)", "$var(medComponents)"); + jansson_set("obj", "medComponents", "$var(medComponents)", "$var(payload)"); + + xlog("L_INFO","Set evSubsc\n"); + + # Set evSubsc + jansson_set("string", "event", "QOS_NOTIF", "$var(event1)"); + jansson_set("string", "notifMethod", "PERIODIC", "$var(event1)"); + jansson_append("obj", "", "$var(event1)", "$var(events)"); + jansson_set("string", "event", "ANI_REPORT", "$var(event2)"); + jansson_set("string", "notifMethod", "ONE_TIME", "$var(event2)"); + jansson_append("obj", "", "$var(event2)", "$var(events)"); + jansson_set("array", "events", "$var(events)", "$var(evSubsc)"); + + jansson_set("obj", "evSubsc", "$var(evSubsc)", "$var(payload)"); + + # Set other parameters in payload + jansson_set("string", "notifUri", "http://N5_BIND_IP:N5_BIND_PORT", "$var(payload)"); + jansson_set("string", "sponStatus", "SPONSOR_DISABLED", "$var(payload)"); + jansson_set("string", "gpsi", "msisdn-$fU", "$var(payload)"); + jansson_set("string", "suppFeat", "4", "$var(payload)"); + jansson_set("string", "ueIpv4", "$var(ue_ip_addr)", "$var(payload)"); + + # Assemble the final JSON request + jansson_set("obj", "ascReqData", "$var(payload)", "$var(json_request)"); + + xlog("L_INFO", "Set headers for the HTTP2 Request\n"); + # Set headers + $var(time_now)=$_s($timef(%a, %d %b %Y %H:%M:%S %Z)); + xlog("L_INFO", "Today is $var(time_now)\n"); + + $var(headers) = "Content-Type: application/json\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-target-nf-type: PCF\r\n"; + $var(headers) = $var(headers) + "accept: application/json\r\n"; + $var(headers) = $var(headers) + "accept: application/problem+json\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-max-rsp-time: 10000\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-service-names: npcf-policyauthorization\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-sender-timestamp: " + $var(time_now); + + xlog("L_INFO","Sending the request to PCF\n"); + # Send the request to PCF + http_client_request_v2pk("POST", "http://SCP_BIND_IP:SCP_BIND_PORT/npcf-policyauthorization/v1/app-sessions", "$var(json_request)", "$var(headers)", "$var(result)"); + + switch ($rc) { + # Success case + case 201: + xlog("L_INFO", "N5 QoS Session successfully Created $rc\n"); + xlog("L_INFO", "HTTP results: $var(result)\n"); + xlog("L_INFO", "HTTP response: $rc\n"); + xlog("L_INFO", "Location Header: $httprhdr(location)\n"); + + # Retrieve the AppSession Id out of the location header in response + # Example URL: "http://SCP_BIND_IP:SCP_BIND_PORT/npcf-policyauthorization/v1/app-sessions/(someSessionID)" + + # Store the url of the lcoation Header in var + $var(url) = $httprhdr(location); + # Get the length of the URL + $var(len) = $(var(url){s.len}); + # Initialize the position variable to the length of the URL + $var(pos) = $var(len); + + # Find the position of the last slash by iterating backwards + while ($var(pos) > 0) { + $var(pos) = $var(pos) - 1; + if ($(var(url){s.substr,$var(pos),1}) == "/") { + break; + } + } + + # Extract the substring after the last slash + # Set the starting position after the last slash + $var(start_pos) = $var(pos) + 1; + # Calculate the length of the substring after the last slash + $var(substring_length) = $var(len) - $var(start_pos); + # Extract the substring after the last slash + $var(app_session) = $(var(url){s.substr,$var(start_pos),$var(substring_length)}); + + xlog("L_INFO", "AppSession Id for user $fU is: $var(app_session)\n"); + + $var(user_id) = $fU; + # Store the AppSession Id in the hash table associated with the UE + $sht(user_data=>$var(user_id)) = $var(app_session); + xlog("L_INFO", "Stored AppSession Id for user $var(user_id): $var(app_session)\n"); + break; + # Failure case + default: + xlog("L_ERR", "N5 QoS authorization failed - Reason code: $rc\n"); + send_reply("412", "Register N5 QoS authorization failed"); + exit; + } +} + +#!endif + +###################################################################### +# Replies to Originating Initial Requests +###################################################################### +onreply_route[MO_reply] { + + xnotice("PCSCF MO_reply: \n Destination URI: $du\n Request URI: $ru\n"); + xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n"); + xnotice("Received IP and Port: ($Ri:$Rp)\n"); + xnotice("Next hop domain: ($nh(d))\n"); + xnotice("Contact header: $ct\n"); + if (is_present_hf("C-Params")) { + remove_hf("Contact"); + remove_hf("C-Params"); + append_hf("Contact: $ct;$hdr(C-Params)\r\n"); + } + +#!ifdef WITH_N5 + # N5 PATCH Request for updating AppSession context + if (t_check_status("180|183|200") && has_body("application/sdp")) { + xlog("L_INFO", "Received early answer in 18x. Patching N5 session in PCF\n"); + if (t_is_retr_async_reply()) { + xlog("L_INFO", "Dropping retransmitted reply which is still currently suspended\n"); + drop(); + } + route(N5_PATCH_REQ); + } +# Terminating N5 AppSession after CANCEL/ERROR + if (is_method("CANCEL") || status=~"[45][0-9][0-9]") { + xlog("L_ALERT", "Terminating AppSession for Call from user $fU due to call end or call failure\n"); + route(N5_MOC_TERM); + } +#!endif + +#!ifdef WITH_IPSEC + sht_lock("ipsec_clients=>ipsec_clients_lock"); + if ($nh(d) != $null && $sht(ipsec_clients=>$nh(d)) != $null) { + # IPSec forward only if its an IPsec client + ipsec_forward("pcscf_location", IPSEC_FORWARD_FLAGS); + } + sht_unlock("ipsec_clients=>ipsec_clients_lock"); +#!endif + # In case of 1xx and 2xx do NAT + if(status=~"[12][0-9][0-9]") + route(NATMANAGE); + +#!ifdef WITH_RX + if (t_check_status("180|183|200") && has_body("application/sdp")) { + xlog("L_DBG", "IMS: Received 183/200 inside orig_initial_reply\n"); + + if (t_is_retr_async_reply()) { + xlog("L_DBG", "Dropping retransmitted reply which is still currently suspended\n"); + drop(); + } + + xlog("L_DBG","Diameter: Orig authorizing media via Rx\n"); + $avp(FTAG_CUSTOM_AVP)=$ft; + $avp(TTAG_CUSTOM_AVP)=$tt; + $avp(CALLID_CUSTOM_AVP)=$ci; + + if (Rx_AAR("MO_aar_reply","orig","",-1) == 0) { + exit; + } + } +} + +route[MO_aar_reply] +{ + # Check reply AVP since the operation is async + switch ($avp(s:aar_return_code)) { + case 1: + xlog("L_DBG", "Diameter: Orig AAR success on media authorization\n"); + break; + default: + xlog("L_ERR", "IMS: AAR failed Orig\n"); + xlog("L_ERR", "IMS: ttag: "+ "$avp(TTAG_CUSTOM_AVP)"); + xlog("L_ERR", "IMS: ftag: "+ "$avp(FTAG_CUSTOM_AVP)"); + xlog("L_ERR", "IMS: callid: "+ "$avp(CALLID_CUSTOM_AVP)"); + # Comment this if you want to allow even if Rx fails + if(dlg_get("$avp(CALLID_CUSTOM_AVP)","$avp(FTAG_CUSTOM_AVP)","$avp(TTAG_CUSTOM_AVP)")){ + dlg_terminate("all", "Sorry no QoS available"); + exit; + } + } +#!endif +} + +###################################################################### +# In-Dialog-Mo-Requests +###################################################################### +route[MO_indialog] { + +#!ifdef WITH_N5 + # N5 PATCH Request for updating AppSession context + if (is_method("INVITE")) { + xlog("L_INFO"," InDialog SDP Answer N5 Request for reINVITE\n"); + route(N5_PATCH_REQ); + } + + # Terminating N5 AppSession after BYE + if (is_method("BYE|CANCEL")) { + route(N5_MOC_TERM); + } +#!endif + + xnotice("PCSCF MO_indialog: \n Destination URI: $du\n Request URI: $ru\n"); + xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n"); + xnotice("Received IP and Port: ($Ri:$Rp)\n"); + xnotice("Next hop domain: ($nh(d))\n"); + xnotice("Contact header: $ct\n"); + setflag(FLT_MOBILE_ORIG); + t_on_reply("MO_indialog_reply"); + + # Append rport only if its a request coming from UE + if (is_request() && ($hdrc(Via) == 1)) { + force_rport(); + } + +#!ifdef WITH_IPSEC + sht_lock("ipsec_clients=>ipsec_clients_lock"); + if ($nh(d) != $null && $sht(ipsec_clients=>$nh(d)) != $null) { + # IPSec forward only if its an IPsec client + ipsec_forward("pcscf_location", IPSEC_FORWARD_FLAGS); + } + sht_unlock("ipsec_clients=>ipsec_clients_lock"); +#!endif +} + +onreply_route[MO_indialog_reply] { + xnotice("PCSCF MO_indialog_reply: \n Destination URI: $du\n Request URI: $ru\n"); + xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n"); + xnotice("Received IP and Port: ($Ri:$Rp)\n"); + xnotice("Next hop domain: ($nh(d))\n"); + xnotice("Contact header: $ct\n"); + +#!ifdef WITH_N5 + # N5 PATCH Request for updating AppSession context + if (t_check_status("180|183|200") && has_body("application/sdp")) { + xlog("L_DBG", "Received early answer in 18x. Patching N5 session in PCF\n"); + if (t_is_retr_async_reply()) { + xlog("L_DBG", "Dropping retransmitted reply which is still currently suspended\n"); + drop(); + } + route(N5_PATCH_REQ); + } +#!endif + +#!ifdef WITH_IPSEC + sht_lock("ipsec_clients=>ipsec_clients_lock"); + if ($nh(d) != $null && $sht(ipsec_clients=>$nh(d)) != $null) { + # IPSec forward only if its an IPsec client + ipsec_forward("pcscf_location", IPSEC_FORWARD_FLAGS); + } + sht_unlock("ipsec_clients=>ipsec_clients_lock"); +#!endif + # In case of 1xx and 2xx do NAT + if(status=~"[12][0-9][0-9]") + route(NATMANAGE); + +#!ifdef WITH_RX + if (t_check_status("180|183|200") && has_body("application/sdp") && !is_method("PRACK")) { + if (t_is_retr_async_reply()) { + xlog("L_DBG", "Dropping retransmitted reply which is still currently suspended\n"); + drop(); + } + + xlog("L_DBG", "IMS: ORIG_SUBSEQUENT reply. This is a 200 OK to a re-INVITE\n"); + xlog("L_DBG","Diameter: Orig authorizing media via Rx\n"); + $avp(FTAG_CUSTOM_AVP)=$ft; + $avp(TTAG_CUSTOM_AVP)=$tt; + $avp(CALLID_CUSTOM_AVP)=$ci; + + if (Rx_AAR("MO_indialog_aar_reply","orig","",-1) == 0) { + exit; + } + } +} + +route[MO_indialog_aar_reply] +{ + # Check reply AVP since the operation is async + switch ($avp(s:aar_return_code)) { + case 1: + xlog("L_DBG", "Diameter: Orig AAR success on media authorization\n"); + break; + default: + xlog("L_ERR", "IMS: AAR failed Orig\n"); + xlog("L_ERR", "IMS: ttag: "+ "$avp(TTAG_CUSTOM_AVP)"); + xlog("L_ERR", "IMS: ftag: "+ "$avp(FTAG_CUSTOM_AVP)"); + xlog("L_ERR", "IMS: callid: "+ "$avp(CALLID_CUSTOM_AVP)"); + # Comment this if you want to allow even if Rx fails + if(dlg_get("$avp(CALLID_CUSTOM_AVP)","$avp(FTAG_CUSTOM_AVP)","$avp(TTAG_CUSTOM_AVP)")){ + dlg_terminate("all", "Sorry no QoS available"); + exit; + } + } +#!endif +} + +#!ifdef WITH_N5 + +# 5G VoNR N5 Policy Authorization PATCH request +route[N5_PATCH_REQ] { + xlog("L_INFO", "IMS: Received 183/200 inside orig_initial_reply\n"); + + # Retrieve the IP/Port of UE + $var(orig_id_ue_ip) = $fU; + $var(ue_sip_ip_addr) = $sht(user_sip_ips=>$var(orig_id_ue_ip)); + xlog("L_INFO", "IP for UE $var(orig_id_ue_ip) is: $var(ue_sip_ip_addr)\n"); + + $var(orig_ue_port) = $fU; + $var(ue_port_sip) = $sht(user_sip_ports=>$var(orig_ue_port)); + xlog("L_INFO", "IP for UE $var(orig_ue_port) is: $var(ue_port_sip)\n"); + + # Retrieve SDP Connection Info and Media Port for UE + $var(sdp_id_ue) = $fU; + $var(ue_sdp_ip) = $sht(user_sdps_ip=>$var(sdp_id_ue)); + xlog("L_INFO", "SDP IP for UE with MSISDN $var(sdp_id_ue) is: $var(ue_sdp_ip)\n"); + + $var(sdp_id_ue_port) = $fU; + $var(ue_sdp_port) = $sht(user_sdps_port=>$var(sdp_id_ue_port)); + xlog("L_INFO", "SDP Port for UE with MSISDN $var(sdp_id_ue_port) is: $var(ue_sdp_port)\n"); + + $var(sdp_id_ue_rtcp_port) = $fU; + $var(ue_sdp_rtcp_port) = $sht(user_sdps_rtcp_port=>$var(sdp_id_ue_rtcp_port)); + xlog("L_INFO", "SDP Port for UE with MSISDN $var(sdp_id_ue_rtcp_port) is: $var(ue_sdp_rtcp_port)\n"); + + # Retrieve SDP Connection Info from SDP Answer + $var(sdp_answ_ip) = $sdp(c:ip); + $var(sdp_answ_port) = $sdp(m0:rtp:port); + $var(sdp_answ_rtcp_port) = $sdp(m0:rtcp:port); + $var(sdp_answ_codec) = $(rb{line.sw,a=rtpmap}{s.select,1, }); + xlog("L_INFO", "SDP Answer connection Info is: $var(sdp_answ_ip), RTP port $var(sdp_answ_port), RTCP Port $var(sdp_answ_rtcp_port) and codec is $var(sdp_answ_codec)\n"); + + # Retrieve AppSession Id + $var(user_id_inv_rep) = $fU; + $var(user_appsess_inv_rep) = $sht(user_data=>$var(user_id_inv_rep)); + xlog("L_INFO", "Stored AppSession Id for user $var(user_id_inv_rep): $var(user_appsess_inv_rep)\n"); + + xlog("L_INFO","Preparing PATCH N5 Message for SDP Answer\n"); + + $var(events) = '[]'; + $var(medComponents) = '{}'; + $var(medSubComps) = '{}'; + $var(evSubsc) = '{}'; + $var(payload) = '{}'; + + # Set afAppId and dnn in payload + jansson_set("string", "afAppId", "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel\"", "$var(payload)"); + jansson_set("string", "dnn", "ims", "$var(payload)"); + + # Set media components + jansson_set("integer", "medCompN", 1, "$var(medComp)"); + jansson_set("string", "qosReference", "qosVoNR", "$var(medComp)"); + jansson_set("string", "medType", "AUDIO", "$var(medComp)"); + jansson_set("array", "codecs", "[\"downlink\\n$var(sdp_answ_codec)\\n\", \"uplink\\n$var(sdp_answ_codec)\\n\"]", "$var(medComp)"); + + # RTP + jansson_set("integer", "fNum", 1, "$var(medSubComp1)"); + jansson_set("array", "fDescs", "[\"permit out 17 from $var(sdp_answ_ip) $var(sdp_answ_port) to $var(ue_sdp_ip) $var(ue_sdp_port)\", \"permit in 17 from $var(ue_sdp_ip) $var(ue_sdp_port) to $var(sdp_answ_ip) $var(sdp_answ_port)\"]", "$var(medSubComp1)"); + jansson_set("string", "fStatus", "ENABLED", "$var(medSubComp1)"); + jansson_set("string", "marBwDl", "5000 Kbps", "$var(medSubComp1)"); + jansson_set("string", "marBwUl", "3000 Kbps", "$var(medSubComp1)"); + jansson_set("string", "flowUsage", "NO_INFO", "$var(medSubComp1)"); + + + # RTCP + jansson_set("integer", "fNum", 2, "$var(medSubComp2)"); + jansson_set("array", "fDescs", "[\"permit out 17 from $var(sdp_answ_ip) $var(sdp_answ_rtcp_port) to $var(ue_sdp_ip) $var(ue_sdp_rtcp_port)\", \"permit in 17 from $var(ue_sdp_ip) $var(ue_sdp_rtcp_port) to $var(sdp_answ_ip) $var(sdp_answ_rtcp_port)\"]", "$var(medSubComp2)"); + jansson_set("string", "fStatus", "ENABLED", "$var(medSubComp2)"); + jansson_set("string", "marBwDl", "5000 Kbps", "$var(medSubComp2)"); + jansson_set("string", "marBwUl", "3000 Kbps", "$var(medSubComp2)"); + jansson_set("string", "flowUsage", "RTCP", "$var(medSubComp2)"); + + # Merging the flows under MediaSubComponent + jansson_set("obj", "0", "$var(medSubComp1)", "$var(medSubComps)"); + jansson_set("obj", "1", "$var(medSubComp2)", "$var(medSubComps)"); + jansson_set("obj", "medSubComps", "$var(medSubComps)", "$var(medComp)"); + + jansson_set("obj", "0", "$var(medComp)", "$var(medComponents)"); + jansson_set("obj", "medComponents", "$var(medComponents)", "$var(payload)"); + + xlog("L_INFO","DEBUG: Set evSubsc\n"); + + # Set evSubsc + jansson_set("string", "event", "QOS_NOTIF", "$var(event1)"); + jansson_set("string", "notifMethod", "PERIODIC", "$var(event1)"); + jansson_append("obj", "", "$var(event1)", "$var(events)"); + jansson_set("string", "event", "ANI_REPORT", "$var(event2)"); + jansson_set("string", "notifMethod", "ONE_TIME", "$var(event2)"); + jansson_append("obj", "", "$var(event2)", "$var(events)"); + jansson_set("array", "events", "$var(events)", "$var(evSubsc)"); + + jansson_set("obj", "evSubsc", "$var(evSubsc)", "$var(payload)"); + + # Set other parameters in payload + jansson_set("string", "notifUri", "http://N5_BIND_IP:N5_BIND_PORT", "$var(payload)"); + jansson_set("string", "sponStatus", "SPONSOR_DISABLED", "$var(payload)"); + jansson_set("string", "gpsi", "msisdn-$fU", "$var(payload)"); + jansson_set("string", "suppFeat", "4", "$var(payload)"); + jansson_set("string", "ueIpv4", "$var(ue_sip_ip_addr)", "$var(payload)"); + + # Assemble the final JSON request + jansson_set("obj", "ascReqData", "$var(payload)", "$var(json_request)"); + + xlog("L_INFO","Set headers for the HTTP2 Request\n"); + # Set headers + $var(time_now)=$_s($timef(%a, %d %b %Y %H:%M:%S %Z)); + xlog("L_INFO", "Today is $var(time_now)\n"); + + # Set Content-type to application/merge-patch+json for compatibility with RFC7386 for JSON PATCH/Merge + $var(headers) = "Content-Type: application/merge-patch+json\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-target-nf-type: PCF\r\n"; + $var(headers) = $var(headers) + "accept: application/json\r\n"; + $var(headers) = $var(headers) + "accept: application/problem+json\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-max-rsp-time: 10000\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-service-names: npcf-policyauthorization\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-sender-timestamp: " + $var(time_now); + + xlog("L_INFO","Sending the request to PCF\n"); + # Send the request to PCF + http_client_request_v2pk("PATCH", "http://SCP_BIND_IP:SCP_BIND_PORT/npcf-policyauthorization/v1/app-sessions/$var(user_appsess_inv_rep)", "$var(json_request)", "$var(headers)", "$var(result)" ); + switch ($rc) { + case 200: + xlog("L_INFO", "N5 QoS Session modification success - reason code: $rc\n"); + xlog("L_INFO", "HTTP results: $var(result)\n"); + xlog("L_INFO", "HTTP response: $rc\n"); + xlog("L_INFO", "cURL Response: $curlerror(error)\n"); + xlog("L_INFO", "Location Header header: $httprhdr(location)\n"); + break; + default: + xlog("L_ERR", "N5 QoS Session modification faild - reason code: $rc\n"); + send_reply("412", "MOC N5 QoS Session modify faild"); + exit; + } +} +#!endif +#!ifdef WITH_N5 +route[N5_MOC_TERM]{ + # Retrieving and paying attention to who ended the call + $var(user_id_call_rel) = $fU; # User Part of the from Header to get the USER + $var(user_appsess_call_rel) = $sht(user_data=>$var(user_id_call_rel)); + if ($var(user_appsess_call_rel) == 0) { + xlog("L_INFO", "we dont have AppSessionID to terminate, doing alternative Method\n"); + # Retrieving and paying attention to who ended the call + $var(user_id_call_rel) = $tU; # User Part of the from Header to get the USER + $var(user_appsess_call_rel) = $sht(user_data=>$var(user_id_call_rel)); + xlog("L_INFO", "Alt-Method : Terminating Stored AppSession for user $var(user_id_call_rel): $var(user_appsess_call_rel)\n"); + } else { + xlog("L_INFO", "We have AppSessionID, doing normal Method\n"); + xlog("L_INFO", "Normal Method : Stored MOC AppSession for user $var(user_id_call_rel): $var(user_appsess_call_rel)\n"); + } + $var(headers) = "X-SIP-Status: Call-Termination\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-target-nf-type: PCF\r\n"; + $var(headers) = $var(headers) + "accept: application/json\r\n"; + $var(headers) = $var(headers) + "accept: application/problem+json\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-max-rsp-time: 10000\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-service-names: npcf-policyauthorization\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-sender-timestamp: " + $var(time_now); + http_client_request_v2pk("POST", "http://SCP_BIND_IP:SCP_BIND_PORT/npcf-policyauthorization/v1/app-sessions/$var(user_appsess_call_rel)/delete", "$var(json_request)", "$var(headers)", "$var(result)" ); + xlog("L_INFO", "Termination resuls: $var(result)\n"); + xlog("L_INFO", "response header: $curlerror(error)\n"); + xlog("L_INFO", "response header: $var(response_code)\n"); + xlog("L_INFO", "response header: $httprhdr(location)\n"); + xlog("L_INFO", "response header: $rc\n"); +} +#!endif diff --git a/pcscf/route/mt.cfg b/pcscf/route/mt.cfg new file mode 100644 index 0000000..6c06e87 --- /dev/null +++ b/pcscf/route/mt.cfg @@ -0,0 +1,568 @@ +###################################################################### +# Terminating, Initial requests +###################################################################### +route[MT] { + xnotice("PCSCF MT: \n Destination URI: $du\n Request URI: $ru\n"); + xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n"); + xnotice("Received IP and Port: ($Ri:$Rp)\n"); + xnotice("Next hop domain: ($nh(d))\n"); + xnotice("Contact header: $ct\n"); + xnotice("Term UE connection information : IP is $dd and Port is $rp \n"); + xnotice("Term P-CSCF connection information : IP is $RAi and Port is $RAp \n"); + set_dlg_profile("term"); + +#!ifdef WITH_N5 + if(is_method("INVITE")) { + route(N5_INIT_MT_REQ); + } +#!endif + +#!ifdef WITH_IPSEC + sht_lock("ipsec_clients=>ipsec_clients_lock"); + if ($nh(d) != $null && $sht(ipsec_clients=>$nh(d)) != $null) { + # IPSec forward only if its an IPsec client + ipsec_forward("pcscf_location", IPSEC_FORWARD_FLAGS); + } + sht_unlock("ipsec_clients=>ipsec_clients_lock"); +#!endif + t_on_reply("MT_reply"); +} + +###################################################################### +# Replies to Originating Initial Requests +###################################################################### +onreply_route[MT_reply] { + xnotice("PCSCF MT_reply: \n Destination URI: $du\n Request URI: $ru\n"); + xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n"); + xnotice("Received IP and Port: ($Ri:$Rp)\n"); + xnotice("Next hop domain: ($nh(d))\n"); + xnotice("Contact header: $ct\n"); + if (!strempty($(ct{tobody.params}))) { + append_hf("C-Params: $(ct{tobody.params})\r\n"); + } + + # In case of 1xx and 2xx do NAT + if(status=~"[12][0-9][0-9]") + route(NATMANAGE); + +#!ifdef WITH_N5 + # N5 PATCH Request for updating AppSession context + if (t_check_status("180|183|200") && has_body("application/sdp")) { + xlog("L_INFO", "Received early answer in 18x. Patching N5 session in PCF\n"); + if (t_is_retr_async_reply()) { + xlog("L_INFO", "Dropping retransmitted reply which is still currently suspended\n"); + drop(); + } + route(N5_PATCH_MT_REQ); + } + + # Terminating N5 AppSession after error response + if (status=~"[45][0-9][0-9]") { + xnotice("Received Error response for the Call. Going to terminate N5 Session\n"); + route(N5_MTC_TERM); + } +#!endif + +#!ifdef WITH_RX + if (t_check_status("180|183|200") && has_body("application/sdp")){ + xnotice("PCSCF MT_reply: \n Destination URI: $du\n Request URI: $ru\n"); + xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n"); + xnotice("Received IP and Port: ($Ri:$Rp)\n"); + xnotice("Contact header: $ct\n"); + xlog("L_DBG", "IMS: Received 183 inside term_initial_reply\n"); + + if (t_is_retr_async_reply()) { + xlog("L_DBG", "Dropping retransmitted reply which is still currently suspended\n"); + drop(); + } + + xlog("L_DBG","Diameter: Term authorizing media via Rx\n"); + $avp(FTAG_CUSTOM_AVP)=$ft; + $avp(TTAG_CUSTOM_AVP)=$tt; + $avp(CALLID_CUSTOM_AVP)=$ci; + + if (Rx_AAR("MT_aar_reply","term","",-1) == 0) { + exit; + } + } +} + +route[MT_aar_reply] +{ + xlog("L_DBG", "IMS: TERM_SESSION_AAR_REPLY\n"); + + # Check reply AVP since the operation is async + switch ($avp(s:aar_return_code)) { + case 1: + xlog("L_DBG", "Diameter: Orig AAR success on media authorization\n"); + break; + default: + xlog("L_ERR", "IMS: AAR failed Orig\n"); + xlog("L_ERR", "IMS: ttag: "+ "$avp(TTAG_CUSTOM_AVP)"); + xlog("L_ERR", "IMS: ftag: "+ "$avp(FTAG_CUSTOM_AVP)"); + xlog("L_ERR", "IMS: callid: "+ "$avp(CALLID_CUSTOM_AVP)"); + # Comment this if you want to allow even if Rx fails + if(dlg_get("$avp(CALLID_CUSTOM_AVP)","$avp(FTAG_CUSTOM_AVP)","$avp(TTAG_CUSTOM_AVP)")){ + dlg_terminate("all", "Sorry no QoS available"); + exit; + } + } +#!endif +} + + +###################################################################### +# In-Dialog-MT-Requests +###################################################################### +route[MT_indialog] { + +#!ifdef WITH_N5 + # N5 PATCH Request for updating AppSession context + if (is_method("INVITE")) { + xlog("L_INFO"," InDialog SDP Change. Sending N5 Request to update appSession context\n"); + route(N5_PATCH_REQ); + } + + # Terminating N5 AppSession after BYE + if (is_method("BYE|CANCEL")) { + xlog("L_INFO"," InDialog Call End/Cancel/Error. Terminating N5 QoS Session\n"); + route(N5_MTC_TERM); + } +#!endif + + xnotice("PCSCF MT_indialog: \n Destination URI: $du\n Request URI: $ru\n"); + xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n"); + xnotice("Received IP and Port: ($Ri:$Rp)\n"); + xnotice("Next hop domain: ($nh(d))\n"); + xnotice("Contact header: $ct\n"); + #resetflag(FLT_MOBILE_ORIG); + t_on_reply("MT_indialog_reply"); + + # Append rport only if its a request coming from UE + if (is_request() && ($hdrc(Via) == 1)) { + force_rport(); + } + +#!ifdef WITH_IPSEC + sht_lock("ipsec_clients=>ipsec_clients_lock"); + if ($nh(d) != $null && $sht(ipsec_clients=>$nh(d)) != $null) { + # IPSec forward only if its an IPsec client + ipsec_forward("pcscf_location", IPSEC_FORWARD_FLAGS); + } + sht_unlock("ipsec_clients=>ipsec_clients_lock"); +#!endif +} + +onreply_route[MT_indialog_reply] { + xnotice("PCSCF MT_indialog_reply: \n Destination URI: $du\n Request URI: $ru\n"); + xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n"); + xnotice("Received IP and Port: ($Ri:$Rp)\n"); + xnotice("Next hop domain: ($nh(d))\n"); + xnotice("Contact header: $ct\n"); + +#!ifdef WITH_N5 + # N5 PATCH Request for updating AppSession context for Indialog reply + if (t_check_status("180|183|200") && has_body("application/sdp")){ + xlog("L_INFO", "Received MT_indialog_reply. Patching N5 session in PCF\n"); + if (t_is_retr_async_reply()) { + xlog("L_INFO", "Dropping retransmitted reply which is still currently suspended\n"); + drop(); + } + route(N5_PATCH_MT_REQ); + } +#!endif + +#!ifdef WITH_IPSEC + sht_lock("ipsec_clients=>ipsec_clients_lock"); + if ($nh(d) != $null && $sht(ipsec_clients=>$nh(d)) != $null) { + # IPSec forward only if its an IPsec client + ipsec_forward("pcscf_location", IPSEC_FORWARD_FLAGS); + } + sht_unlock("ipsec_clients=>ipsec_clients_lock"); +#!endif + # In case of 1xx and 2xx do NAT + if(status=~"[12][0-9][0-9]") + route(NATMANAGE); + +#!ifdef WITH_RX + if (t_check_status("180|183|200") && has_body("application/sdp") && !is_method("PRACK")) { + if (t_is_retr_async_reply()) { + xlog("L_DBG", "Dropping retransmitted reply which is still currently suspended\n"); + drop(); + } + + xlog("L_DBG", "IMS: TERM_SUBSEQUENT reply. This is a 200 OK to a re-INVITE\n"); + xlog("L_DBG","Diameter: Term authorizing media via Rx\n"); + $avp(FTAG_CUSTOM_AVP)=$ft; + $avp(TTAG_CUSTOM_AVP)=$tt; + $avp(CALLID_CUSTOM_AVP)=$ci; + + if (Rx_AAR("MT_indialog_aar_reply","term","",-1) == 0) { + exit; + } + } +} + +route[MT_indialog_aar_reply] +{ + # Check reply AVP since the operation is async + switch ($avp(s:aar_return_code)) { + case 1: + xlog("L_DBG", "Diameter: Orig AAR success on media authorization\n"); + break; + default: + xlog("L_ERR", "IMS: AAR failed Orig\n"); + xlog("L_ERR", "IMS: ttag: "+ "$avp(TTAG_CUSTOM_AVP)"); + xlog("L_ERR", "IMS: ftag: "+ "$avp(FTAG_CUSTOM_AVP)"); + xlog("L_ERR", "IMS: callid: "+ "$avp(CALLID_CUSTOM_AVP)"); + # Comment this if you want to allow even if Rx fails + if(dlg_get("$avp(CALLID_CUSTOM_AVP)","$avp(FTAG_CUSTOM_AVP)","$avp(TTAG_CUSTOM_AVP)")){ + dlg_terminate("all", "Sorry no QoS available"); + exit; + } + } +#!endif +} + +#!ifdef WITH_N5 + +# Route Logic for N5 Requests +route[N5_INIT_MT_REQ] { + + # Storing IDs and IPs from UE into variables to use them later in the N5 Request + $var(term_ue_ip) = $dd; + $var(term_sip_ue_port) = $rp; + $var(pcscf_sip_ip) = $Ri; + $var(pcscf_sip_port) = $Rp; + + xlog("L_INFO", "SIP Connection Info for Term UE $var(term_ue_ip) $var(term_sip_ue_port)\n"); + xlog("L_INFO", "SIP Connection Info for P-CSCF is: $var(pcscf_sip_ip) $var(pcscf_sip_port)\n"); + + $var(term_user_id_req_ip) = $tU; + # Store the IP in the hash table associated with the UE + $sht(user_sip_ips=>$var(term_user_id_req_ip)) = $var(term_ue_ip); + xlog("L_INFO", "SIP/SDP IP Info for Term UE MSISDN $var(term_user_id_req_ip): $var(term_ue_ip)\n"); + + $var(term_user_id_req_port) = $tU; + # Store the Port in the hash table associated with the UE + $sht(user_sip_ports=>$var(term_user_id_req_port)) = $var(term_sip_ue_port); + xlog("L_INFO", "SIP Port Info for UE MSISDN $var(term_user_id_req_port): $var(term_sip_ue_port)\n"); + + xlog("L_INFO", "IMS: MTC INVITE TO $tU\n"); + # Retrieving SDP Connection Info and Media Port for UE + $var(sdp_src_ip) = $sdp(c:ip); + $var(sdp_src_port) = $sdp(m0:rtp:port); + $var(orig_ue_sdp_rtcp_port) = $sdp(m0:rtcp:port); + $var(sdp_mline_raw) = $sdp(m0:raw); + + xlog("L_INFO", "SDP Info From INVITE: $sdp(c:ip) -- $sdp(m0:rtp:port) -- $sdp(m0:rtcp:port)\n"); + + $var(call_id_sdp_ip) = $ci; + # Store the SDP IP in the hash table associated with the Call-Id + $sht(user_sdps_ip=>$var(call_id_sdp_ip)) = $var(sdp_src_ip); + + $var(ret_call_id_sdp_ip) = $ci; + $var(sdp_src_ip) = $sht(user_sdps_ip=>$var(ret_call_id_sdp_ip)); + xlog("L_INFO", "SDP IP of orig UE $fU Call-ID $var(call_id_sdp_ip): $var(sdp_src_ip)\n"); + + $var(sdp_call_id_port) = $ci; + # Store SDP Media Port in the hash table associated with the Call-Id + $sht(user_sdps_port=>$var(sdp_call_id_port)) = $var(sdp_src_port); + xlog("L_INFO", "SDP Port for MTC Call-ID $var(sdp_call_id_port) is: $var(sdp_src_port)\n"); + + $var(sdp_call_id_rtcp_port) = $ci; + #Store SDP RTCP Port in the hash table associated with the Call-Id + $sht(user_sdps_rtcp_port=>$var(sdp_call_id_rtcp_port)) = $var(orig_ue_sdp_rtcp_port); + + $var(sdp_call_id_rtcp_port) = $ci; + $var(orig_ue_sdp_rtcp_port) = $sht(user_sdps_rtcp_port=>$var(sdp_call_id_rtcp_port)); + xlog("L_INFO", "SDP RTCP Port for UE with MSISDN $fU is: $var(orig_ue_sdp_rtcp_port)\n"); + + xlog("L_INFO", "Preparing QoS N5 Message to PCF for INVITE To term UE\n"); + + $var(events) = '[]'; + $var(medComponents) = '{}'; + $var(medSubComps) = '{}'; + $var(evSubsc) = '{}'; + $var(payload) = '{}'; + + # Set afAppId and dnn in payload + # TODO: Get the value from SIP Header + jansson_set("string", "afAppId", "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel\"", "$var(payload)"); + jansson_set("string", "dnn", "ims", "$var(payload)"); + + # Set medComponents + jansson_set("integer", "medCompN", 1, "$var(medComp)"); + jansson_set("string", "qosReference", "qosVoNR", "$var(medComp)"); + jansson_set("string", "medType", "AUDIO", "$var(medComp)"); + jansson_set("array", "codecs", "[\"downlink\\noffer\\n\", \"uplink\\nanswer\\n\"]", "$var(medComp)"); + + # RTP + jansson_set("integer", "fNum", 1, "$var(medSubComp1)"); + jansson_set("array", "fDescs", "[\"permit out 17 from $var(sdp_src_ip) $var(sdp_src_port) to $dd 49000-51000\", \"permit in 17 from $dd 49000-51000 to $var(sdp_src_ip) $var(sdp_src_port)\"]", "$var(medSubComp1)"); + jansson_set("string", "fStatus", "ENABLED", "$var(medSubComp1)"); + jansson_set("string", "marBwDl", "5000 Kbps", "$var(medSubComp1)"); + jansson_set("string", "marBwUl", "3000 Kbps", "$var(medSubComp1)"); + jansson_set("string", "flowUsage", "NO_INFO", "$var(medSubComp1)"); + + # RTCP + jansson_set("integer", "fNum", 2, "$var(medSubComp2)"); + jansson_set("array", "fDescs", "[\"permit out 17 from $var(sdp_src_ip) $var(orig_ue_sdp_rtcp_port) to $dd 49000-51000\", \"permit in 17 from $dd 49000-51000 to $var(sdp_src_ip) $var(orig_ue_sdp_rtcp_port)\"]", "$var(medSubComp2)"); + jansson_set("string", "fStatus", "ENABLED", "$var(medSubComp2)"); + jansson_set("string", "marBwDl", "5000 Kbps", "$var(medSubComp2)"); + jansson_set("string", "marBwUl", "3000 Kbps", "$var(medSubComp2)"); + jansson_set("string", "flowUsage", "RTCP", "$var(medSubComp2)"); + + # Merging the flows under MediaSubComponent + jansson_set("obj", "0", "$var(medSubComp1)", "$var(medSubComps)"); + jansson_set("obj", "1", "$var(medSubComp2)", "$var(medSubComps)"); + jansson_set("obj", "medSubComps", "$var(medSubComps)", "$var(medComp)"); + + jansson_set("obj", "0", "$var(medComp)", "$var(medComponents)"); + jansson_set("obj", "medComponents", "$var(medComponents)", "$var(payload)"); + + xlog("L_INFO","DEBUG: Set evSubsc\n"); + + # Set evSubsc + jansson_set("string", "event", "QOS_NOTIF", "$var(event1)"); + jansson_set("string", "notifMethod", "PERIODIC", "$var(event1)"); + jansson_append("obj", "", "$var(event1)", "$var(events)"); + jansson_set("string", "event", "ANI_REPORT", "$var(event2)"); + jansson_set("string", "notifMethod", "ONE_TIME", "$var(event2)"); + jansson_append("obj", "", "$var(event2)", "$var(events)"); + jansson_set("array", "events", "$var(events)", "$var(evSubsc)"); + + jansson_set("obj", "evSubsc", "$var(evSubsc)", "$var(payload)"); + + # Set other parameters in payload + jansson_set("string", "notifUri", "http://N5_BIND_IP:N5_BIND_PORT", "$var(payload)"); + jansson_set("string", "sponStatus", "SPONSOR_DISABLED", "$var(payload)"); + jansson_set("string", "gpsi", "msisdn-$tU", "$var(payload)"); + jansson_set("string", "suppFeat", "2", "$var(payload)"); + jansson_set("string", "ueIpv4", "$dd", "$var(payload)"); + + # Assemble the final JSON request + jansson_set("obj", "ascReqData", "$var(payload)", "$var(json_request)"); + + xlog("L_INFO","DEBUG: Set headers for the HTTP2 Request\n"); + # Set headers + $var(time_now)=$_s($timef(%a, %d %b %Y %H:%M:%S %Z)); + xlog("L_INFO", "Today is $var(time_now)\n"); + + $var(headers) = "Content-Type: application/json\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-target-nf-type: PCF\r\n"; + $var(headers) = $var(headers) + "accept: application/json\r\n"; + $var(headers) = $var(headers) + "accept: application/problem+json\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-max-rsp-time: 10000\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-service-names: npcf-policyauthorization\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-sender-timestamp: " + $var(time_now); + + xlog("L_INFO","Sending the request to PCF\n"); + # Send the request to PCF + http_client_request_v2pk("POST", "http://SCP_BIND_IP:SCP_BIND_PORT/npcf-policyauthorization/v1/app-sessions", "$var(json_request)", "$var(headers)", "$var(result)" ); + + switch ($rc) { + # Success case + case 201: + xlog("L_INFO", "N5 QoS Session successfully Created $rc\n"); + xlog("L_INFO", "HTTP results: $var(result)\n"); + xlog("L_INFO", "HTTP response: $rc\n"); + xlog("L_INFO", "Location Header: $httprhdr(location)\n"); + + # Retrieve the AppSession Id out of the location header in response + # Example URL: "http://SCP_BIND_IP:SCP_BIND_PORT/npcf-policyauthorization/v1/app-sessions/(someSessionID)" + + # Store the url of the lcoation Header in var + $var(url) = $httprhdr(location); + # Get the length of the URL + $var(len) = $(var(url){s.len}); + # Initialize the position variable to the length of the URL + $var(pos) = $var(len); + + # Find the position of the last slash by iterating backwards + while ($var(pos) > 0) { + $var(pos) = $var(pos) - 1; + if ($(var(url){s.substr,$var(pos),1}) == "/") { + # We've found the last slash + break; + } + } + + # Extract the substring after the last slash + # Set the starting position after the last slash + $var(start_pos) = $var(pos) + 1; + # Calculate the length of the substring after the last slash + $var(substring_length) = $var(len) - $var(start_pos); + # Extract the substring after the last slash + $var(mtc_app_session) = $(var(url){s.substr,$var(start_pos),$var(substring_length)}); + + xlog("L_INFO", "AppSession Id for user $tU is: $var(mtc_app_session)\n"); + + $var(term_user_id) = $tU; + + # Store the AppSession Id in the hash table associated with the UE + $sht(user_data=>$var(term_user_id)) = $var(mtc_app_session); + xlog("L_INFO", "Stored AppSession for user $var(term_user_id): $var(mtc_app_session)\n"); + break; + default: + xlog("L_ERR", "N5 QoS Session faild - Reason code: $rc\n"); + send_reply("412", "MTC N5 QoS Session Creation faild"); + exit; + } +} + +# 5G VoNR N5 Policy Authorization PATCH request +route[N5_PATCH_MT_REQ] { + xlog("L_INFO", "N5_PATCH_MT_REQ, building N5 PATCH Request\n"); + + # Retrieve SDP Connection Info and Media Port for UE + $var(sdp_call_id) = $ci; + $var(orig_ue_sdp_ip) = $sht(user_sdps_ip=>$var(sdp_call_id)); + xlog("L_INFO", "SDP IP for UE with MSISDN $fU Call-ID $var(sdp_call_id) is: $var(orig_ue_sdp_ip)\n"); + + $var(sdp_call_id_port) = $ci; + $var(orig_ue_sdp_port) = $sht(user_sdps_port=>$var(sdp_call_id_port)); + xlog("L_INFO", "SDP RTP Port for UE with MSISDN $fU Call-ID $var(sdp_call_id_port) is: $var(orig_ue_sdp_port)\n"); + + $var(sdp_call_id_rtcp_port) = $ci; + $var(orig_ue_sdp_rtcp_port) = $sht(user_sdps_rtcp_port=>$var(sdp_call_id_rtcp_port)); + xlog("L_INFO", "SDP RTCP Port for UE with MSISDN $fU Call-ID $var(sdp_call_id_rtcp_port) is: $var(orig_ue_sdp_rtcp_port)\n"); + + # Retrieve SDP Connection Info from SDP Answer + $var(sdp_answ_ip) = $sdp(c:ip); + $var(sdp_answ_port) = $sdp(m0:rtp:port); + $var(sdp_answ_rtcp_port) = $sdp(m0:rtcp:port); + $var(sdp_answ_codec) = $(rb{line.sw,a=rtpmap}{s.select,1, }); + xlog("L_INFO", "SDP Answer connection Info is: $var(sdp_answ_ip), RTP port $var(sdp_answ_port), RTCP Port $var(sdp_answ_rtcp_port) and codec is $var(sdp_answ_codec)\n"); + + # Retrieve AppSession + $var(mtc_resp_app_id) = $tU; + $var(user_appsess_mtc_rep) = $sht(user_data=>$var(mtc_resp_app_id)); + xlog("L_INFO", "Stored MTC AppSession for user $var(mtc_resp_app_id): $var(user_appsess_mtc_rep)\n"); + + xlog("L_INFO","Preparing PATCH N5 Message for SDP Answer\n"); + + $var(events) = '[]'; + $var(medComponents) = '{}'; + $var(medSubComps) = '{}'; + $var(evSubsc) = '{}'; + $var(payload) = '{}'; + + # Set afAppId and dnn in payload + jansson_set("string", "afAppId", "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel\"", "$var(payload)"); + jansson_set("string", "dnn", "ims", "$var(payload)"); + + # Set medComponents + jansson_set("integer", "medCompN", 1, "$var(medComp)"); + jansson_set("string", "qosReference", "qosVoNR", "$var(medComp)"); + jansson_set("string", "medType", "AUDIO", "$var(medComp)"); + jansson_set("array", "codecs", "[\"downlink\\n$var(sdp_answ_codec)\\n\", \"uplink\\n$var(sdp_answ_codec)\\n\"]", "$var(medComp)"); + + # RTP + jansson_set("integer", "fNum", 1, "$var(medSubComp1)"); + jansson_set("array", "fDescs", "[\"permit out 17 from $var(orig_ue_sdp_ip) $var(orig_ue_sdp_port) to $var(sdp_answ_ip) $var(sdp_answ_port)\", \"permit in 17 from $var(sdp_answ_ip) $var(sdp_answ_port) to $var(orig_ue_sdp_ip) $var(orig_ue_sdp_port)\"]", "$var(medSubComp1)"); + jansson_set("string", "fStatus", "ENABLED", "$var(medSubComp1)"); + jansson_set("string", "marBwDl", "5000 Kbps", "$var(medSubComp1)"); + jansson_set("string", "marBwUl", "3000 Kbps", "$var(medSubComp1)"); + jansson_set("string", "flowUsage", "NO_INFO", "$var(medSubComp1)"); + + # RTCP + jansson_set("integer", "fNum", 2, "$var(medSubComp2)"); + jansson_set("array", "fDescs", "[\"permit out 17 from $var(orig_ue_sdp_ip) $var(orig_ue_sdp_rtcp_port) to $var(sdp_answ_ip) $var(sdp_answ_rtcp_port)\", \"permit in 17 from $var(sdp_answ_ip) $var(sdp_answ_rtcp_port) to $var(orig_ue_sdp_ip) $var(orig_ue_sdp_rtcp_port)\"]", "$var(medSubComp2)"); + jansson_set("string", "fStatus", "ENABLED", "$var(medSubComp2)"); + jansson_set("string", "marBwDl", "6000 Kbps", "$var(medSubComp2)"); + jansson_set("string", "marBwUl", "5000 Kbps", "$var(medSubComp2)"); + jansson_set("string", "flowUsage", "RTCP", "$var(medSubComp2)"); + + # Merging the flows under MediaSubComponent + jansson_set("obj", "0", "$var(medSubComp1)", "$var(medSubComps)"); + jansson_set("obj", "1", "$var(medSubComp2)", "$var(medSubComps)"); + jansson_set("obj", "medSubComps", "$var(medSubComps)", "$var(medComp)"); + + jansson_set("obj", "0", "$var(medComp)", "$var(medComponents)"); + jansson_set("obj", "medComponents", "$var(medComponents)", "$var(payload)"); + + xlog("L_INFO","DEBUG: Set evSubsc\n"); + + # Set evSubsc + jansson_set("string", "event", "QOS_NOTIF", "$var(event1)"); + jansson_set("string", "notifMethod", "PERIODIC", "$var(event1)"); + jansson_append("obj", "", "$var(event1)", "$var(events)"); + jansson_set("string", "event", "ANI_REPORT", "$var(event2)"); + jansson_set("string", "notifMethod", "ONE_TIME", "$var(event2)"); + jansson_append("obj", "", "$var(event2)", "$var(events)"); + jansson_set("array", "events", "$var(events)", "$var(evSubsc)"); + + jansson_set("obj", "evSubsc", "$var(evSubsc)", "$var(payload)"); + + # Set other parameters in payload + jansson_set("string", "notifUri", "http://N5_BIND_IP:N5_BIND_PORT", "$var(payload)"); + jansson_set("string", "sponStatus", "SPONSOR_DISABLED", "$var(payload)"); + jansson_set("string", "gpsi", "msisdn-$tU", "$var(payload)"); + jansson_set("string", "suppFeat", "2", "$var(payload)"); + jansson_set("string", "ueIpv4", "$si", "$var(payload)"); + + # Assemble the final JSON request + jansson_set("obj", "ascReqData", "$var(payload)", "$var(json_request)"); + + xlog("L_INFO","DEBUG: Set headers for the HTTP2 Request\n"); + # Set headers + $var(time_now)=$_s($timef(%a, %d %b %Y %H:%M:%S %Z)); + xlog("L_INFO", "Today is $var(time_now)\n"); + + # Set Content-type to application/merge-patch+json for compatibility with RFC7386 for JSON PATCH/Merge + $var(headers) = "Content-Type: application/merge-patch+json\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-target-nf-type: PCF\r\n"; + $var(headers) = $var(headers) + "accept: application/json\r\n"; + $var(headers) = $var(headers) + "accept: application/problem+json\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-max-rsp-time: 10000\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-service-names: npcf-policyauthorization\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-sender-timestamp: " + $var(time_now); + + xlog("L_INFO","Sending the request to PCF\n"); + # Send the request to PCF + http_client_request_v2pk("PATCH", "http://SCP_BIND_IP:SCP_BIND_PORT/npcf-policyauthorization/v1/app-sessions/$var(user_appsess_mtc_rep)", "$var(json_request)", "$var(headers)", "$var(result)" ); + switch ($rc) { + case 200: + xlog("L_INFO", "N5 QoS Session modification success - reason code: $rc\n"); + xlog("L_INFO", "HTTP results: $var(result)\n"); + xlog("L_INFO", "HTTP response: $rc\n"); + xlog("L_INFO", "cURL Response: $curlerror(error)\n"); + xlog("L_INFO", "Location Header header: $httprhdr(location)\n"); + break; + default: + xlog("L_ERR", "N5 QoS Session modification faild - reason code: $rc\n"); + send_reply("412", "MTC N5 QoS Session modify faild"); + exit; + } +} + +route[N5_MTC_TERM] { + xlog("L_ALERT","Terminating AppSession For Call for User $tU due to call END\n"); + # Retrieve appSession based on To URI + $var(mtc_resp_app_id) = $tU; + $var(user_appsess_mtc_rep) = $sht(user_data=>$var(mtc_resp_app_id)); + if $var(user_appsess_mtc_rep) == 0 { + xlog("L_INFO", "No AppSession Id found to terminate. Trying using From URI\n"); + + # Retrieve appSession based on From URI + $var(mtc_resp_app_id) = $fU; + $var(user_appsess_mtc_rep) = $sht(user_data=>$var(mtc_resp_app_id)); + xlog("L_INFO", "Alt-Method : Terminating Stored AppSession for user $var(mtc_resp_app_id): $var(user_appsess_mtc_rep)\n"); + } else { + xlog("L_INFO", "Normal Method : MTC AppSession for user $var(mtc_resp_app_id): $var(user_appsess_mtc_rep)\n"); + } + + $var(headers) = "X-SIP-Status: De-Registration\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-target-nf-type: PCF\r\n"; + $var(headers) = $var(headers) + "accept: application/json\r\n"; + $var(headers) = $var(headers) + "accept: application/problem+json\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-max-rsp-time: 10000\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-service-names: npcf-policyauthorization\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-sender-timestamp: " + $var(time_now); + + http_client_request_v2pk("POST", "http://SCP_BIND_IP:SCP_BIND_PORT/npcf-policyauthorization/v1/app-sessions/$var(user_appsess_mtc_rep)/delete", "$var(json_request)", "$var(headers)", "$var(result)" ); + xlog("L_INFO", "cURL header: $curlerror(error)\n"); + xlog("L_INFO", "HTTP response: $rc\n"); +} +#!endif diff --git a/pcscf/route/register.cfg b/pcscf/route/register.cfg new file mode 100644 index 0000000..2550c08 --- /dev/null +++ b/pcscf/route/register.cfg @@ -0,0 +1,488 @@ +###################################################################### +# Route for handling Registrations: +###################################################################### +route[REGISTER] { + # Provide some statistics + if ($sht(a=>$ci::start_time) == $null || $sht(a=>$ci::start_time) == 0) { + $sht(a=>$ci::start_time) = $TV(Sn); + } + xnotice("PCSCF REGISTER: \n Destination URI: $du\n Request URI: $ru\n"); + xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n"); + xnotice("Received IP and Port: ($Ri:$Rp)\n"); + xnotice("Contact header: $ct\n"); + + # Strip Transport from RURI: + $ru = $(ru{re.subst,/;transport=[A-Za-z]*//g}); + + if (is_present_hf("Contact")) { + pcscf_save_pending("pcscf_location"); + } else { + send_reply("403", "No contact header"); + exit; + } + +#!ifdef WITH_N5 + $var(reg_exp) = $expires(min); + xlog("L_INFO","Expire for $fu is :$var(reg_exp)\n"); + + # Trying a dirty workaround to make it only excute after IPSec tunnel to prevent double excution + if ($expires(min) != 0 && is_present_hf("Security-Verify")) { + route(REGISTER_N5_REQ); + } + + if ($expires(min) == 0) { + xlog("L_ALERT","Delete N5 Session for $fu due to de-register\n"); + route(REG_N5_TERMINATE); + } +#!endif + + # Strip additional Tags from RURI: + if ($rU == $null) + $ru = "sip:"+$rd; + else + $ru = "sip:"+$rU+"@"+$rd; + +#!ifdef WITH_RX + if ($expires(min) != 0) { + xlog("L_DBG","Subscribing to signalling bearer status\n"); + + Rx_AAR_Register("REG_AAR_REPLY", "pcscf_location"); + switch ($retcode) { + case -1: + # There was an error sending the AAR-Request: + xlog("L_ERR", "Diameter: AAR failed on subscription to signalling\n"); + send_reply("403", "Can't register to QoS for signalling"); + exit; + break; + case 0: + # We are waiting for an async reply, just exit here. + exit; + break; + case 1: + # We did not need to send AAR, so just continue as normal + route(REGISTER_CONTINUE); + break; + } + } else { + # Proceed with Registering: + route(REGISTER_CONTINUE); + } + exit; +} + +route[REG_AAR_REPLY] { + switch ($avp(s:aar_return_code)) { + case 1: + xlog("L_DBG", "Diameter: AAR success on subscription to signalling\n"); + break; + default: + xlog("L_ERR", "Diameter: AAR failed on subscription to signalling\n"); + send_reply("403", "Can't register to QoS for signalling"); + exit; + } + # Proceed with Registering: + route(REGISTER_CONTINUE); +} + +route[REGISTER_CONTINUE] { +#!endif + append_hf("Path: \r\n"); + + remove_hf("Supported"); + append_hf("Supported: path\r\n"); + remove_hf("Require"); + append_hf("Require: path\r\n"); + + # Add a visited Network-ID-Header: + if (is_present_hf("P-Visited-Network-ID")) { + $var(new_hdr) = "NETWORKNAME, "+$hdr(P-Visited-Network-ID); + append_hf("P-Visited-Network-ID: $var(new_hdr)\r\n"); + } else { + append_hf("P-Visited-Network-ID: NETWORKNAME\r\n"); + } +#!ifdef WITH_SBC +#!ifndef WITH_SBC_CALL + t_on_failure("SBC_failure"); + # Choose an SBC to send the call to: + if (!ds_select_dst(DISPATCHER_LIST_SBC, "4")) { + send_reply("503", "Service Unavailable (SBC failure)"); + exit; + } +#!else + t_on_failure("REGISTER_failure"); +#!endif +#!else + t_on_failure("REGISTER_failure"); +#!endif + t_on_reply("REGISTER_reply"); + # Forward request: + route(RELAY); + exit; +} + +# Replies for REGISTER requests: +###################################################################### +onreply_route[REGISTER_reply] +{ +#!ifdef WITH_IMS_HDR_CACHE + if (is_present_hf("Service-Route")) { + $sht(serviceroutes=>$ci) = $hdr(Service-Route); + } else { + if ($sht(serviceroutes=>$ci) != $null) { + append_hf("Service-Route: $sht(serviceroutes=>$ci)\r\n"); + msg_apply_changes(); + } + } + if (is_present_hf("P-Associated-URI")) { + $sht(associateduris=>$ci) = $hdr(P-Associated-URI); + } else { + if ($sht(associateduris=>$ci) != $null) { + append_hf("P-Associated-URI: $sht(associateduris=>$ci)\r\n"); + msg_apply_changes(); + } + } +#!endif + + if (t_check_status("200")) { +#!ifdef WITH_IPBLOCK + $sht(failedauth=>$T_req($si)) = $null; +#!endif + pcscf_save("pcscf_location"); + +#!ifdef WITH_NATPING +#!ifdef WITH_PING_UDP + #if ($T_req($pr) == "udp") { + if ($pr == "udp") { + sht_lock("natping=>natpinglock"); + if ($(T_req($hdr(Security-Client))) =~ ".*ipsec-3gpp.*") { + $var(sec_client) = $(T_req($hdr(Security-Client))); + xnotice("Security-Client=$var(sec_client)\n"); + $var(sc_port_c) = $(var(sec_client){re.subst,/.*port-c=([0-9]*).*$/\1/s}); + xnotice("port-c=$var(sc_port_c)\n"); + $var(sc_port_s) = $(var(sec_client){re.subst,/.*port-s=([0-9]*).*$/\1/s}); + xnotice("port-s=$var(sc_port_s)\n"); + $var(ouri) = "sip:"+$T_req($si)+":"+$var(sc_port_s); + } else { + $var(ouri) = "sip:"+$T_req($si)+":"+$T_req($sp); + } + $sht(natping=>$var(ouri)) = $(T_req($ct){nameaddr.uri}); + sht_unlock("natping=>natpinglock"); + + sht_lock("natpingfrom=>natpingfromlock"); + if ($(T_req($hdr(Security-Verify))) =~ ".*ipsec-3gpp.*") { + $var(sec_verify) = $(T_req($hdr(Security-Verify))); + xnotice("Security-Verify=$var(sec_verify)\n"); + $var(sv_port_c) = $(var(sec_verify){re.subst,/.*port-c=([0-9]*).*$/\1/s}); + xnotice("port-c=$var(sv_port_c)\n"); + $var(sv_port_s) = $(var(sec_verify){re.subst,/.*port-s=([0-9]*).*$/\1/s}); + xnotice("port-s=$var(sv_port_s)\n"); + + $sht(natpingfrom=>$var(ouri)) = "udp:"+$T_req($Ri)+":"+$var(sv_port_c); + } else { + $sht(natpingfrom=>$var(ouri)) = "udp:"+$T_req($Ri)+":"+$T_req($Rp); + } + sht_unlock("natpingfrom=>natpingfromlock"); + } +#!endif +#!ifdef WITH_PING_TCP + #if ($T_req($pr) == "tcp") { + if ($pr == "tcp") { + sht_lock("natping=>natpinglock"); + if ($(T_req($hdr(Security-Client))) =~ ".*ipsec-3gpp.*") { + $var(sec_client) = $(T_req($hdr(Security-Client))); + xnotice("Security-Client=$var(sec_client)\n"); + $var(sc_port_c) = $(var(sec_client){re.subst,/.*port-c=([0-9]*).*$/\1/s}); + xnotice("port-c=$var(sc_port_c)\n"); + $var(sc_port_s) = $(var(sec_client){re.subst,/.*port-s=([0-9]*).*$/\1/s}); + xnotice("port-s=$var(sc_port_s)\n"); + $var(ouri) = "sip:"+$T_req($si)+":"+$var(sc_port_s)+";transport=tcp"; + } else { + $var(ouri) = "sip:"+$T_req($si)+":"+$T_req($sp)+";transport=tcp"; + } + $sht(natping=>$var(ouri)) = $(T_req($ct){nameaddr.uri}); + sht_unlock("natping=>natpinglock"); + + sht_lock("natpingfrom=>natpingfromlock"); + if ($(T_req($hdr(Security-Verify))) =~ ".*ipsec-3gpp.*") { + $var(sec_verify) = $(T_req($hdr(Security-Verify))); + xnotice("Security-Verify=$var(sec_verify)\n"); + $var(sv_port_c) = $(var(sec_verify){re.subst,/.*port-c=([0-9]*).*$/\1/s}); + xnotice("port-c=$var(sv_port_c)\n"); + $var(sv_port_s) = $(var(sec_verify){re.subst,/.*port-s=([0-9]*).*$/\1/s}); + xnotice("port-s=$var(sv_port_s)\n"); + + $sht(natpingfrom=>$var(ouri)) = "tcp:"+$T_req($Ri)+":"+$var(sv_port_c); + } else { + $sht(natpingfrom=>$var(ouri)) = "tcp:"+$T_req($Ri)+":"+$T_req($Rp); + } + sht_unlock("natpingfrom=>natpingfromlock"); + } +#!endif +#!ifdef WITH_PING_TLS + #if ($T_req($pr) == "tls") { + if ($pr == "tls") { + sht_lock("natping=>natpinglock"); + if ($(T_req($hdr(Security-Client))) =~ ".*ipsec-3gpp.*") { + $var(sec_client) = $(T_req($hdr(Security-Client))); + xnotice("Security-Client=$var(sec_client)\n"); + $var(sc_port_c) = $(var(sec_client){re.subst,/.*port-c=([0-9]*).*$/\1/s}); + xnotice("port-c=$var(sc_port_c)\n"); + $var(sc_port_s) = $(var(sec_client){re.subst,/.*port-s=([0-9]*).*$/\1/s}); + xnotice("port-s=$var(sc_port_s)\n"); + $var(ouri) = "sip:"+$T_req($si)+":"+$var(sc_port_s)+";transport=tls"; + } else { + $var(ouri) = "sip:"+$T_req($si)+":"+$T_req($sp)+";transport=tls"; + } + $sht(natping=>$var(ouri)) = $(T_req($ct){nameaddr.uri}); + sht_unlock("natping=>natpinglock"); + + sht_lock("natpingfrom=>natpingfromlock"); + if ($(T_req($hdr(Security-Verify))) =~ ".*ipsec-3gpp.*") { + $var(sec_verify) = $(T_req($hdr(Security-Verify))); + xnotice("Security-Verify=$var(sec_verify)\n"); + $var(sv_port_c) = $(var(sec_verify){re.subst,/.*port-c=([0-9]*).*$/\1/s}); + xnotice("port-c=$var(sv_port_c)\n"); + $var(sv_port_s) = $(var(sec_verify){re.subst,/.*port-s=([0-9]*).*$/\1/s}); + xnotice("port-s=$var(sv_port_s)\n"); + + $sht(natpingfrom=>$var(ouri)) = "tls:"+$T_req($Ri)+":"+$var(sv_port_c); + } else { + $sht(natpingfrom=>$var(ouri)) = "tls:"+$T_req($Ri)+":"+$T_req($Rp); + } + sht_unlock("natpingfrom=>natpingfromlock"); + } +#!endif +#!endif + #update stats for register reply on success + $var(start_secs) = $(sht(a=>$ci::start_time){s.select,0,.}); + $var(start_usecs) = $(sht(a=>$ci::start_time){s.select,1,.}); + $var(diff_secs) = $TV(s) - $var(start_secs); + $var(diff_usecs) = $TV(u) - $var(start_usecs); + $var(diff_ms) = $var(diff_secs)*1000 + ($var(diff_usecs)/1000); + $sht(a=>$ci::start_time)=0; + $var(stat_add) = "+" + $var(diff_ms); + xlog("L_DBG", "REGISTER SUCCESS[$ci] took $var(stat_add)ms\n"); + update_stat("register_success", "+1"); + update_stat("register_time", "$var(stat_add)"); +#!ifdef WITH_IPSEC + sht_lock("ipsec_clients=>ipsec_clients_lock"); + if ($sht(ipsec_clients=>$T_req($si)) != $null) { + # IPSec forward only if its an IPsec client + ipsec_forward("pcscf_location", IPSEC_FORWARD_FLAGS); + } + sht_unlock("ipsec_clients=>ipsec_clients_lock"); + } + else { + if (t_check_status("401")) { + if($(T_req($hdr(Security-Client))) != $null && ipsec_create("pcscf_location", IPSEC_DELETE_UNUSED_TUNNELS)!=1) { + send_reply("503", "Service Unavailable (Create ipsec failed)"); + } + sht_lock("ipsec_clients=>ipsec_clients_lock"); + if ($sht(ipsec_clients=>$T_req($si)) != $null) { + $var(sec_client) = $(T_req($hdr(Security-Client))); + xnotice("Security-Client=$var(sec_client)\n"); + $var(sc_port_c) = $(var(sec_client){re.subst,/.*port-c=([0-9]*).*$/\1/s}); + xnotice("port-c=$var(sc_port_c)\n"); + $var(sc_port_s) = $(var(sec_client){re.subst,/.*port-s=([0-9]*).*$/\1/s}); + xnotice("port-s=$var(sc_port_s)\n"); + } + sht_unlock("ipsec_clients=>ipsec_clients_lock"); + xnotice("Expires=$(T_req($expires(min)))\n"); + if (is_present_hf("WWW-Authenticate")) { + # Remove ck and ik: + $var(old_hdr) = $hdr(WWW-Authenticate); + xnotice("Old header - WWW-Authenticate=$var(old_hdr)\n"); + remove_hf("WWW-Authenticate"); + $var(new_hdr) = $(hdr(WWW-Authenticate){re.subst,/(, *)?(ck|ik)=\"\w+\"//gi}); + if ($(var(new_hdr){s.len}) > 0) { + append_hf("WWW-Authenticate: $var(new_hdr)\r\n"); + } + xnotice("New header - WWW-Authenticate=$var(new_hdr)\n"); + } + } +#!endif + } + exit; +} + +# Negative replies to REGISTER requests: +###################################################################### +failure_route[REGISTER_failure] +{ + +#!ifdef WITH_N5 + # Terminate N5 Session on Reg Failure + if (t_check_status("403|408|[5-6][0-9][0-9]")) { + route(REG_N5_TERMINATE); + } +#!endif + +#!ifdef WITH_IPBLOCK + if (t_check_status("403|[5-6][0-9][0-9]")) { + if ($sht(failedauth=>$si) != $null) + $sht(failedauth=>$si) = $sht(failedauth=>$si) + 1; + else + $sht(failedauth=>$si) = 1; + if ($sht(failedauth=>$si) > 10) { + xlog("L_ALERT","ALERT: blocking $rm from $fu (IP:$si:$sp), more than 5 failed auth requests!\n"); + xlog("Blocking traffic from $si\n"); + $sht(ipban=>$si) = 1; + } + update_stat("register_failed", "+1"); + } +#!endif + if (t_check_status("408")) { + send_reply("504","Server Time-Out"); + update_stat("register_failed", "+1"); + exit; + } + +} + +#!ifdef WITH_N5 + +# N5 Policy Authorization - Create Application session context for SIP Registration +route[REGISTER_N5_REQ] +{ + xlog("L_INFO","SIP Registration - Starting N5 QoS Auth for $fu\n"); + + $var(events) = '[]'; + $var(medComponents) = '{}'; + $var(medSubComps) = '{}'; + $var(evSubsc) = '{}'; + $var(payload) = '{}'; + + # Set afAppId and dnn in payload + jansson_set("string", "afAppId", "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel\"", "$var(payload)"); # adding a note that this could be improved in future to get the value SIP Header + jansson_set("string", "dnn", "ims", "$var(payload)"); + + # Set media components in payload + jansson_set("integer", "medCompN", 0, "$var(medComp)"); + jansson_set("string", "qosReference", "qosVoNR", "$var(medComp)"); + jansson_set("string", "medType", "CONTROL", "$var(medComp)"); + + jansson_set("integer", "fNum", 0, "$var(medSubComp)"); + jansson_set("array", "fDescs", "[\"permit out ip from $RAi $RAp to $si $sp\", \"permit in ip from $si $sp to $RAi $RAp\"]", "$var(medSubComp)"); + jansson_set("string", "fStatus", "ENABLED", "$var(medSubComp)"); + jansson_set("string", "flowUsage", "AF_SIGNALLING", "$var(medSubComp)"); + # jansson_set("string", "marBwDl", "5000 Kbps", "$var(medSubComp)"); + # jansson_set("string", "marBwUl", "3000 Kbps", "$var(medSubComp)"); + jansson_set("obj", "0", "$var(medSubComp)", "$var(medSubComps)"); + jansson_set("obj", "medSubComps", "$var(medSubComps)", "$var(medComp)"); + + jansson_set("obj", "0", "$var(medComp)", "$var(medComponents)"); + jansson_set("obj", "medComponents", "$var(medComponents)", "$var(payload)"); + + # Set evSubsc + jansson_set("string", "event", "QOS_NOTIF", "$var(event1)"); + jansson_set("string", "notifMethod", "PERIODIC", "$var(event1)"); + jansson_append("obj", "", "$var(event1)", "$var(events)"); + jansson_set("string", "event", "ANI_REPORT", "$var(event2)"); + jansson_set("string", "notifMethod", "ONE_TIME", "$var(event2)"); + jansson_append("obj", "", "$var(event2)", "$var(events)"); + jansson_set("array", "events", "$var(events)", "$var(evSubsc)"); + + jansson_set("obj", "evSubsc", "$var(evSubsc)", "$var(payload)"); + + # Set other parameters in payload + jansson_set("string", "notifUri", "http://N5_BIND_IP:N5_BIND_PORT", "$var(payload)"); + jansson_set("string", "sponStatus", "SPONSOR_DISABLED", "$var(payload)"); + jansson_set("string", "supi", "imsi-$au", "$var(payload)"); + jansson_set("string", "suppFeat", "2", "$var(payload)"); + jansson_set("string", "ueIpv4", "$si", "$var(payload)"); + + # Assemble the final JSON request + jansson_set("obj", "ascReqData", "$var(payload)", "$var(json_request)"); + + # Set HTTP2 request headers + $var(time_now)=$_s($timef(%a, %d %b %Y %H:%M:%S %Z)); + $var(headers) = "Content-Type: application/json\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-target-nf-type: PCF\r\n"; + $var(headers) = $var(headers) + "accept: application/json\r\n"; + $var(headers) = $var(headers) + "accept: application/problem+json\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-max-rsp-time: 10000\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-service-names: npcf-policyauthorization\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-sender-timestamp: " + $var(time_now); + + xlog("L_INFO","SIP Registration. Sending N5 QoS Auth for $fu to PCF\n"); + # Send the request to PCF + http_client_request_v2pk("POST", "http://SCP_BIND_IP:SCP_BIND_PORT/npcf-policyauthorization/v1/app-sessions", "$var(json_request)", "$var(headers)", "$var(result)" ); + + switch ($rc) { + # Success case + case 201: + xlog("L_INFO", "N5 QoS Session successfully Created $rc\n"); + xlog("L_INFO", "HTTP results: $var(result)\n"); + xlog("L_INFO", "HTTP response: $rc\n"); + xlog("L_INFO", "Location Header: $httprhdr(location)\n"); + + # Retrieve the AppSession Id out of the location Header if the resopnse is 201. + # Example URL: "http://SCP_BIND_IP:SCP_BIND_PORT/npcf-policyauthorization/v1/app-sessions/(someSessionID)" + + # Store the url of the location header + $var(url) = $httprhdr(location); + # Get the length of the URL + $var(len) = $(var(url){s.len}); + # Initialize the position variable to the length of the URL + $var(pos) = $var(len); + + # Find the position of the last slash by iterating backwards + while ($var(pos) > 0) { + $var(pos) = $var(pos) - 1; + if ($(var(url){s.substr,$var(pos),1}) == "/") { + break; + } + } + + # Extract the substring after the last slash + $var(start_pos) = $var(pos) + 1; + $var(end_pos) = $var(len) - $var(start_pos); + $var(app_session) = $(var(url){s.substr,$var(start_pos),$var(end_pos)}); + + xlog("L_INFO", "AppSession Id for user $au is: $var(app_session)\n"); + + $var(user_id) = $au; + # Store the AppSession Id in the hash table associated with the UE + $sht(user_data=>$var(user_id)) = $var(app_session); + xlog("L_INFO", "Stored AppSession Id for user $var(user_id): $var(app_session)\n"); + + $var(ue_imsi) = $au; + $var(ue_imsi_reg_ip) = $si; + # Store the AppSession in the hash table associated with the UE + $sht(user_ids=>$var(ue_imsi_reg_ip)) = $var(ue_imsi); + xlog("L_INFO", "Stored IMSI for IP $var(ue_imsi_reg_ip) is: $var(ue_imsi)\n"); + break; + # Failure case + default: + xlog("L_ERR", "N5 QoS Session authorization failed - Reason code: $rc\n"); + send_reply("412", "Register N5 QoS authorization failed"); + exit; + } +} + +# N5 Policy Authorization - Application session termination for SIP De-registration +route[REG_N5_TERMINATE] +{ + xlog("L_ALERT","SIP De-Registration for $fu - Terminating N5 AppSession\n"); + # Retrieve the AppSession Id from the hash table + $var(user_id_dereg) = $fU; + $var(user_appsess_dereg) = $sht(user_data=>$var(user_id_dereg)); + xlog("L_INFO", "Terminating stored AppSession for user $var(user_id_dereg): $var(user_appsess_dereg)\n"); + + $var(headers) = "X-SIP-Status: De-Registration\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-target-nf-type: PCF\r\n"; + $var(headers) = $var(headers) + "accept: application/json\r\n"; + $var(headers) = $var(headers) + "accept: application/problem+json\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-max-rsp-time: 10000\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-discovery-service-names: npcf-policyauthorization\r\n"; + $var(headers) = $var(headers) + "3gpp-sbi-sender-timestamp: " + $var(time_now); + + http_client_request_v2pk("POST", "http://SCP_BIND_IP:SCP_BIND_PORT/npcf-policyauthorization/v1/app-sessions/$var(user_appsess_dereg)/delete", "$var(json_request)", "$var(headers)", "$var(result)" ); + xlog("Termination resuls: $var(result)\n"); + xlog("L_ALERT", "cURL response: $curlerror(error)\n"); + xlog("L_INFO", "HTTP results: $var(result)\n"); + xlog("L_INFO", "HTTP response: $rc\n"); + xlog("L_INFO", "Location Header: $httprhdr(location)\n"); +} + +#!endif diff --git a/pcscf/route/rtp.cfg b/pcscf/route/rtp.cfg new file mode 100644 index 0000000..d9fb3de --- /dev/null +++ b/pcscf/route/rtp.cfg @@ -0,0 +1,216 @@ +# RTPProxy control +route[ENC_SRTP] { + add_rr_param(";rm=1"); + $avp(rtpproxy_offer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=force SRTP AVP"; + $avp(rtpproxy_answer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=remove RTP AVP"; +} + +route[DEC_SRTP] { + add_rr_param(";rm=2"); + $avp(rtpproxy_offer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=remove RTP AVP"; + $avp(rtpproxy_answer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=force SRTP AVP"; +} + +route[ENC_WS_RTP] { + add_rr_param(";rm=3"); + $avp(rtpproxy_offer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=force RTP AVPF"; + $avp(rtpproxy_answer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=remove RTP AVP"; +} + +route[DEC_WS_RTP] { + add_rr_param(";rm=4"); + $avp(rtpproxy_offer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=remove RTP AVP"; + $avp(rtpproxy_answer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=force RTP AVPF"; +} + +route[ENC_WSS_RTP] { + add_rr_param(";rm=5"); + $avp(rtpproxy_offer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=force SRTP AVPF DTLS=passive"; + $avp(rtpproxy_answer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=remove RTP AVP"; +} + +route[DEC_WSS_RTP] { + add_rr_param(";rm=6"); + $avp(rtpproxy_offer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=remove RTP AVP"; + $avp(rtpproxy_answer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=force SRTP AVPF DTLS=passive"; +} + +route[ENC_RTP] { + add_rr_param(";rm=7"); + $avp(rtpproxy_offer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=force RTP AVP"; + $avp(rtpproxy_answer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=remove RTP AVP"; +} + +route[DEC_RTP] { + add_rr_param(";rm=8"); + $avp(rtpproxy_offer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=remove RTP AVP"; + $avp(rtpproxy_answer_flags) = "flags=loop-protect replace-origin replace-session-connection ICE=force RTP AVP"; +} + +# RTPProxy control +route[NATMANAGE] { +#!ifdef WITH_DEBUG + if (is_request()) + xlog("REQUEST: $rm $ru ($si:$sp, $ci)\n"); + else + xlog("REPLY: $rs $rr ($rm, $si:$sp, $ci)\n"); + + if (is_direction("downstream")) + xlog(" downstream\n"); + else + xlog(" upstream\n"); + + xlog(" Offer: $avp(rtpproxy_offer_flags)\n"); + xlog(" Answer: $avp(rtpproxy_answer_flags)\n"); + if (isflagset(FLT_MOBILE_ORIG)) { + xlog(" mo\n"); + } else { + xlog(" mt\n"); + } +#!endif + if ((is_reply() && ($T_req($tt) != $null)) || (is_request() && has_totag())) { + xlog("L_DBG", "Request had ToTag."); + #if((is_request() && !check_route_param("rm=")) || (is_reply() && !isflagset(FLT_RTP))) { + if(!check_route_param("rm=") && !isflagset(FLT_RTP)) { + xlog("L_DBG", "No RM Param\n"); + return; + } + if (($fU != $null && is_in_profile("caller", "$fU")) || + ($tU != $null && is_in_profile("callee", "$tU"))) { + # In-Dialog Request from MO side + if (is_request() && isflagset(FLT_MOBILE_ORIG)) { + add_contact_alias(); + } else if (is_reply() && !isflagset(FLT_MOBILE_ORIG)) { + add_contact_alias(); + } + } else if (($fU != $null && is_in_profile("callee", "$fU")) || + ($tU != $null && is_in_profile("caller", "$tU"))) { + # In-Dialog Request from MT side + if (is_request() && !isflagset(FLT_MOBILE_ORIG)) { + add_contact_alias(); + } else if (is_reply() && isflagset(FLT_MOBILE_ORIG)) { + add_contact_alias(); + } + } + } else { + if (is_reply() && !isflagset(FLT_MOBILE_ORIG)) { + xlog("L_DBG", "3) ADD_contact_alias();"); + add_contact_alias(); + } + } + + if (isflagset(FLT_MOBILE_ORIG)) { + $avp(setid) = 1; + $avp(extra_id) = "mo"; + } else { + $avp(setid) = 1; +# $avp(setid) = 2; + $avp(extra_id) = "mt"; + } + + if(!t_is_set("onreply_route")) t_on_reply("NAT_REPLY"); + if(!t_is_set("failure_route")) t_on_failure("NATMANAGE"); + + if (is_method("BYE") || t_is_failure_route()) { + rtpengine_manage(); + return; + } + + setflag(FLT_RTP); + + if (!has_body("application/sdp")) + return; + +#!ifdef REMOVE_BITALIGNED_AMR + route(REMOVE_BITALIGNED); +#!endif + +#!ifndef FORCE_RTPRELAY + if (!isflagset(FLT_NAT) || !check_route_param("rm=")) + return; +#!endif + + # Fix for calling between UEs not supporting preconditioning + if(sdp_get_line_startswith("$avp(mline)", "a=inactive")) { + xlog("m-line: $avp(mline)\n"); + sdp_remove_line_by_prefix("a=inactive"); + $sdp(body) = $sdp(body) + "a=sendrecv\r\n"; + msg_apply_changes(); + } + + if ((is_reply() && ($T_req($tt) != $null)) || (is_request() && has_totag())) { + if (($fU != $null && is_in_profile("caller", "$fU")) || + ($tU != $null && is_in_profile("callee", "$tU"))) { + # In-Dialog Request from MO side + if (is_request() && isflagset(FLT_MOBILE_ORIG)) { + rtpengine_manage(); + } else if (is_reply() && !isflagset(FLT_MOBILE_ORIG)) { + rtpengine_manage(); + } + } else if (($fU != $null && is_in_profile("callee", "$fU")) || + ($tU != $null && is_in_profile("caller", "$tU"))) { + # In-Dialog Request from MT side + if (is_request() && !isflagset(FLT_MOBILE_ORIG)) { + rtpengine_manage(); + } else if (is_reply() && isflagset(FLT_MOBILE_ORIG)) { + rtpengine_manage(); + } + } + } else { + # Initial Requests + if ($avp(rtpproxy_offer_flags) == $null) + return; + if ($avp(rtpproxy_answer_flags) == $null) + return; + + if (is_request() && isflagset(FLT_MOBILE_ORIG)) { + set_dlg_profile("caller", "$fU"); + rtpengine_manage($avp(rtpproxy_offer_flags)); + } else if (is_reply() && !isflagset(FLT_MOBILE_ORIG)) { + set_dlg_profile("callee", "$tU"); + rtpengine_manage($avp(rtpproxy_answer_flags)); + } + } +} + +# manage incoming replies +onreply_route[NAT_REPLY] { + # In case of 1xx and 2xx do NAT + if(status=~"[12][0-9][0-9]") + route(NATMANAGE); +} + +route[REMOVE_BITALIGNED] { + if (sdp_get_line_startswith("$avp(mline)", "m=")) { + # xlog("m-line: $avp(mline)\n"); + sdp_get("$avp(sdp)"); + # xlog("\n$avp(sdp)\n"); + $var(x) = -1; + $var(remove) = ""; + $var(codec) = $(avp(mline){s.select,$var(x), }); + # xlog("$$var(codec) => $var(codec)\n"); + while ($(var(codec){s.int}) > 0) { + # xlog("$var(x)) $$var(codec) => $var(codec)\n"); + $var(s) = "a=fmtp:"+$var(codec); + # xlog("$$var(s) => $var(s)\n"); + $var(fmtp) = $(avp(sdp){line.sw,$var(s)}); + # xlog("$$var(fmtp) => $var(fmtp)\n"); + if ($var(fmtp) =~ "a=fmtp:"+$var(codec)+" mode-change-capability.*") { + # xlog("Match: $var(codec)\n"); + if ($var(remove) == "") { + $var(remove) = $var(codec); + } else { + $var(remove) = $var(remove)+","+$var(codec); + } + } + $var(codec) = $(avp(mline){s.select,$var(x), }); + $var(x) = $var(x) - 1; + } + # xlog("$$var(remove) => $var(remove)\n"); + if ($var(remove) != "") { + sdp_remove_codecs_by_id($var(remove), "audio"); + msg_apply_changes(); + } + } +} + diff --git a/pcscf/route/websocket.cfg b/pcscf/route/websocket.cfg new file mode 100644 index 0000000..954defe --- /dev/null +++ b/pcscf/route/websocket.cfg @@ -0,0 +1,62 @@ +event_route[xhttp:request] { + set_reply_close(); + set_reply_no_connect(); + +#!ifdef WITH_XMLRPC + if ($hu =~ "^/RPC") { + route(XMLRPC); + exit; + } +#!endif + + if ($Rp != MY_WS_PORT +#!ifdef WITH_TLS + && $Rp != MY_WSS_PORT +#!endif + ) { + xlog("L_WARN", "HTTP request received on $Rp\n"); + xhttp_reply("403", "Forbidden - HTTP request received on $Rp", "", ""); + exit; + } + + if ($hdr(Upgrade)=~"websocket" + && in_list("Upgrade", $hdr(Connection), ",") + && $rm=~"GET") { + + # Validate Host - make sure the client is using the correct + # alias for WebSockets + if ($hdr(Host) == $null || !is_myself("sip:" + $hdr(Host))) { + xlog("L_WARN", "Bad host $hdr(Host)\n"); + xhttp_reply("403", "Forbidden - invalid host", "", ""); + exit; + } + +#!ifdef WEBSOCKET_WEBSERVER + # Validate Origin - make sure the client is from the authorised website + if ($hdr(Origin) != "http://"+WEBSOCKET_WEBSERVER +#!ifdef WITH_TLS + && $hdr(Origin) != "https://"+WEBSOCKET_WEBSERVER +#!endif + ) { + xlog("L_WARN", "Unauthorised client $hdr(Origin)\n"); + xhttp_reply("403", "Forbidden - invalid website", "", ""); + exit; + } +#!endif + + # ws_handle_handshake() exits (no further configuration file + # processing of the request) when complete. + if (ws_handle_handshake()) { + # Optional... cache some information about the + # successful connection + exit; + } + } + + # xhttp_reply("200", "OK", "text/html", "Wrong URL $hu"); + xhttp_reply("404", "Not Found", "", ""); +} + +event_route[websocket:closed] { + xlog("L_DBG", "WebSocket connection from $si:$sp has closed\n"); +} diff --git a/pcscf/route/xmlrpc.cfg b/pcscf/route/xmlrpc.cfg new file mode 100644 index 0000000..50571c0 --- /dev/null +++ b/pcscf/route/xmlrpc.cfg @@ -0,0 +1,27 @@ +# XMLRPC routing +route[XMLRPC] { + # allow XMLRPC from localhost + if ((method=="POST" || method=="GET") +#!ifdef XMLRPC_WHITELIST_1 +&& ((src_ip == XMLRPC_WHITELIST_1) +#!ifdef XMLRPC_WHITELIST_2 + || (src_ip == XMLRPC_WHITELIST_2) +#!endif +#!ifdef XMLRPC_WHITELIST_3 + || (src_ip == XMLRPC_WHITELIST_3) +#!endif +) +#!endif +) { + # close connection only for xmlrpclib user agents (there is a bug in + # xmlrpclib: it waits for EOF before interpreting the response). + if ($hdr(User-Agent) =~ "xmlrpclib") + set_reply_close(); + set_reply_no_connect(); + dispatch_rpc(); + exit; + } + send_reply("403", "Forbidden"); + exit; +} + diff --git a/pcscf/sems/etc/methodmap.conf b/pcscf/sems/etc/methodmap.conf new file mode 100644 index 0000000..8641a01 --- /dev/null +++ b/pcscf/sems/etc/methodmap.conf @@ -0,0 +1,2 @@ +OPTIONS=>refuse_with_200 +REGISTER=>register diff --git a/pcscf/sems/etc/mo.sbcprofile.conf b/pcscf/sems/etc/mo.sbcprofile.conf new file mode 100644 index 0000000..39a2527 --- /dev/null +++ b/pcscf/sems/etc/mo.sbcprofile.conf @@ -0,0 +1,78 @@ +# transparent SBC profile +# +# This implements a transparent B2BUA - all possible options are commented + +# defaults: transparent +#RURI=$r +#From=$f +#To=sip:$rU@ims.voiceblue.com + +#Call-ID +#Call-ID=$ci-ngv + +## routing +# outbound proxy: +outbound_proxy=sip:mo@$si:$sp +# force outbound proxy (in-dialog requests)? +#force_outbound_proxy=yes +# destination IP[:port] for outgoing requests +next_hop_ip=$si +next_hop_port=$sp +# use next_hop for replies, too? +#next_hop_for_replies=yes +# outbound interface to use (interface ID) +#outbound_interface=extern + +## RTP relay +# enable RTP relaying (bridging): +enable_rtprelay=no +# force symmetric RTP (start with passive mode): +#rtprelay_force_symmetric_rtp=yes +# use symmetric RTP indication from P-MsgFlags flag 2 +#rtprelay_msgflags_symmetric_rtp=yes + +## filters: +header_filter=whitelist +header_list=Diversion,P-Asserted-Identity,Privacy,Allow,Event,Expires,Accept,User-Agent,Subscription-State,P-Access-Network-Info,P-Route,C-Params,Feature-Caps +#header_filter=blacklist +#header_list= +#header_list=P-App-Param,P-App-Name +message_filter=blacklist +message_list=SUBSCRIBE +sdp_filter=whitelist +#sdpfilter_list=g722,pcma,pcmu,gsm,amr,h264,telephone-event +sdpfilter_list=g722,pcma,pcmu,gsm,amr,amr-wb,amr-wb/16000,h264,telephone-event +codec_preference=g722,amr-wb,amr-wb/16000,pcmu,pcma,gsm,amr +sdp_anonymize=yes +#sdp_anonymize=no +# Filter A-Lines: +sdp_alines_filter=blacklist +sdp_alinesfilter_list=crypto,nortpproxy + +## Transcoding +enable_transcoder=on_missing_compatible +#enable_transcoder=always +transcoder_codecs=amr,pcma,pcmu +#transcoder_codecs=amr-wb/16000,amr-wb,g722,amr,pcma,pcmu +prefer_existing_codecs=yes +# Minimum G711! +callee_codeccaps=pcma,pcmu + +## reply translations +# translate some 6xx class replies to 4xx class: +#reply_translations="603=>488 Not acceptable here|600=>406 Not Acceptable" + +# From the mobile network +enable_aleg_session_timer=no +aleg_session_expires=120 +aleg_minimum_timer=90 +aleg_maximum_timer=180 + +# From our network +enable_session_timer=no +session_expires=120 +minimum_timer=90 +maximum_timer=7200 + +#session_refresh_method=UPDATE_FALLBACK_INVITE +#accept_501_reply=yes diff --git a/pcscf/sems/etc/monitoring.conf b/pcscf/sems/etc/monitoring.conf new file mode 100644 index 0000000..b61c1ca --- /dev/null +++ b/pcscf/sems/etc/monitoring.conf @@ -0,0 +1,20 @@ + +#run_garbage_collector=[yes | no] +# +# run garbage collection on expired session info? +# Default: no +# +run_garbage_collector = yes + +#garbage_collector_interval=10 +# +# run garbage collection every n seconds +# Default: 10 +# +#garbage_collector_interval = 20 + +# retain_samples_s=10 +# +# retain "sample" type values for n seconds +# +#retain_samples_s=20 diff --git a/pcscf/sems/etc/mt.sbcprofile.conf b/pcscf/sems/etc/mt.sbcprofile.conf new file mode 100644 index 0000000..fac9d2c --- /dev/null +++ b/pcscf/sems/etc/mt.sbcprofile.conf @@ -0,0 +1,80 @@ +# transparent SBC profile +# +# This implements a transparent B2BUA - all possible options are commented + +# defaults: transparent +#RURI=$r +#From=$f +#To=sip:$rU@$td + +#Call-ID +#Call-ID=$ci_leg2 + +## routing +# outbound proxy: +outbound_proxy=sip:mt@$si:$sp +# force outbound proxy (in-dialog requests)? +#force_outbound_proxy=yes +# destination IP[:port] for outgoing requests +#next_hop_ip=$si +#next_hop_port=$sp +# use next_hop for replies, too? +#next_hop_for_replies=yes +# outbound interface to use (interface ID) +#outbound_interface=extern + +## RTP relay +# enable RTP relaying (bridging): +enable_rtprelay=no +# force symmetric RTP (start with passive mode): +#rtprelay_force_symmetric_rtp=yes +# use symmetric RTP indication from P-MsgFlags flag 2 +#rtprelay_msgflags_symmetric_rtp=yes + +## filters: +header_filter=whitelist +header_list=Diversion,P-Asserted-Identity,Privacy,P-Route,P-NAT,P-Source,Allow,Event,Expires,Accept,User-Agent,Subscription-State,P-Route,C-Params +#header_filter=blacklist +#header_list= +#header_list=P-App-Param,P-App-Name +#message_filter=blacklist +#message_list=OPTIONS +sdp_filter=whitelist +sdpfilter_list=g722,pcma,pcmu,gsm,amr-wb,amr-wb/16000,amr,h264,telephone-event +sdp_anonymize=yes +# Filter A-Lines: +sdp_alines_filter=blacklist +sdp_alinesfilter_list=crypto,nortpproxy + +## Transcoding +enable_transcoder=on_missing_compatible +transcoder_codecs=pcma,pcmu,amr +prefer_existing_codecs=yes +callee_codeccaps=amr + +## reply translations +# translate some 6xx class replies to 4xx class: +#reply_translations="603=>488 Not acceptable here|600=>406 Not Acceptable" + +## session timer: + +# From our network +enable_aleg_session_timer=no +aleg_session_expires=120 +aleg_minimum_timer=90 +aleg_maximum_timer=7200 + +# From the mobile network +enable_session_timer=no +session_expires=120 +minimum_timer=90 +maximum_timer=180 + +#session_refresh_method=UPDATE_FALLBACK_INVITE +#accept_501_reply=yes + +## Registration Caching +enable_reg_caching=no +min_reg_expires=7200 +max_ua_expires=120 + diff --git a/pcscf/sems/etc/nocache.sbcprofile.conf b/pcscf/sems/etc/nocache.sbcprofile.conf new file mode 100644 index 0000000..ec3262d --- /dev/null +++ b/pcscf/sems/etc/nocache.sbcprofile.conf @@ -0,0 +1,38 @@ +# transparent SBC profile +# +# This implements a transparent B2BUA - all possible options are commented + +# defaults: transparent + +## routing +# outbound proxy: +outbound_proxy=sip:$si:$sp +# force outbound proxy (in-dialog requests)? +#force_outbound_proxy=yes +# destination IP[:port] for outgoing requests +#next_hop_ip=$si +#next_hop_port=$sp +# use next_hop for replies, too? +#next_hop_for_replies=yes +# outbound interface to use (interface ID) +#outbound_interface=extern + +## filters: +#header_filter=whitelist +#header_list=Diversion,P-Asserted-Identity,Privacy,P-Route,P-Destination,P-Source +#header_filter=blacklist +#header_list= +#header_list=P-App-Param,P-App-Name +#message_filter=blacklist +#message_list=OPTIONS +sdp_filter=whitelist +sdpfilter_list=g722,pcma,pcmu,isac,ilbc,gsm,telephone-event +sdp_anonymize=yes +# Filter A-Lines: +sdp_alines_filter=blacklist +sdp_alinesfilter_list=crypto,nortpproxy + +## Registration Caching +enable_reg_caching=no +min_reg_expires=60 +max_ua_expires=60 diff --git a/pcscf/sems/etc/refuse.sbcprofile.conf b/pcscf/sems/etc/refuse.sbcprofile.conf new file mode 100644 index 0000000..3ea3d62 --- /dev/null +++ b/pcscf/sems/etc/refuse.sbcprofile.conf @@ -0,0 +1 @@ +refuse_with="403 Forbidden" diff --git a/pcscf/sems/etc/refuse_with_200.sbcprofile.conf b/pcscf/sems/etc/refuse_with_200.sbcprofile.conf new file mode 100644 index 0000000..de0a306 --- /dev/null +++ b/pcscf/sems/etc/refuse_with_200.sbcprofile.conf @@ -0,0 +1 @@ +refuse_with="200 OK" diff --git a/pcscf/sems/etc/register.sbcprofile.conf b/pcscf/sems/etc/register.sbcprofile.conf new file mode 100644 index 0000000..c8f1ae2 --- /dev/null +++ b/pcscf/sems/etc/register.sbcprofile.conf @@ -0,0 +1,28 @@ +# transparent SBC profile +# +# This implements a transparent B2BUA - all possible options are commented + +# defaults: transparent + +## routing +# outbound proxy: +#outbound_proxy=sip:$si:$sp +# force outbound proxy (in-dialog requests)? +#force_outbound_proxy=yes +# destination IP[:port] for outgoing requests +#next_hop_ip=$si +#next_hop_port=$sp +# use next_hop for replies, too? +#next_hop_for_replies=yes +# outbound interface to use (interface ID) +#outbound_interface=extern + +## filters: +#header_filter=whitelist +#header_list=P-Visited-Network-ID + +## Registration Caching +enable_reg_caching=yes +min_reg_expires=120 +#min_reg_expires=57600 +max_ua_expires=120 diff --git a/pcscf/sems/etc/rurimap.conf b/pcscf/sems/etc/rurimap.conf new file mode 100644 index 0000000..867ad7e --- /dev/null +++ b/pcscf/sems/etc/rurimap.conf @@ -0,0 +1 @@ +ims.voiceblue.com=>mo diff --git a/pcscf/sems/etc/sbc.conf b/pcscf/sems/etc/sbc.conf new file mode 100644 index 0000000..dd206a5 --- /dev/null +++ b/pcscf/sems/etc/sbc.conf @@ -0,0 +1,62 @@ + +# profiles - comma-separated list of call profiles to load +# +# .sbcprofile.conf is loaded from module config +# path (the path where this file resides) +profiles=mo,mt,register + +# active call profile - comma separated list, first non-empty is used +# +# o active_profile= always use +# +# o active_profile=$(ruri.user) use user part of INVITE Request URI +# +# o active_profile=$(paramhdr) use "profile" option in P-App-Param header +# +# o any replacement pattern +# +active_profile=$H(SBC),register + +# regex_maps - comma-separated list of regex maps to load at startup, for $M() +# +# regex=>value maps for which names are given here are loaded from +# this path, e.g. src_ipmap.conf, ruri_map.conf, usermap.conf +# +#regex_maps=src_ipmap + +## RFC4028 Session Timer +# default configuration - can be overridden by call profiles + +# - enables the session timer ([yes,no]; default: no) +# +#enable_session_timer=yes + +# - set the "Session-Expires" parameter for the session timer. +# +#session_expires=120 + +# - set the "Min-SE" parameter for the session timer. +# +#minimum_timer=90 + +# session refresh (Session Timer, RFC4028) method +# +# INVITE - use re-INVITE +# UPDATE - use UPDATE +# UPDATE_FALLBACK_INVITE - use UPDATE if indicated in Allow, re-INVITE otherwise +# +# Default: UPDATE_FALLBACK_INVITE +# +#session_refresh_method=UPDATE + +# accept_501_reply - accept 501 reply as successful refresh? [yes|no] +# +# Default: yes +# +#accept_501_reply=no + +# handle OPTIONS messages in the core? (with limits etc) +# Default: no +core_options_handling=yes + + diff --git a/pcscf/sems/etc/stats.conf b/pcscf/sems/etc/stats.conf new file mode 100644 index 0000000..57babe1 --- /dev/null +++ b/pcscf/sems/etc/stats.conf @@ -0,0 +1,5 @@ +# IP of the monitoring interface: +monit_udp_ip=127.0.0.1 + +# port the statistics server should listen to: +monit_udp_port=5040 diff --git a/pcscf/sems/etc/xmlrpc2di.conf b/pcscf/sems/etc/xmlrpc2di.conf new file mode 100644 index 0000000..9c9bf05 --- /dev/null +++ b/pcscf/sems/etc/xmlrpc2di.conf @@ -0,0 +1,42 @@ +# server_ip : IP to bind XMLRPC server to +# leave empty for ANY interface +server_ip=127.0.0.1 + +# port to bind XMLRPC server to +xmlrpc_port=8090 + +# run multi-threaded server? +# Default: yes +# +# multithreaded = yes + +# threads to run - this many requests can be processed in parallel +# Default: 5 +# +# threads=5 + +# export all DI functions with the function call 'di'? +# defaults to: yes +# export_di=yes + +# +# these DI interfaces are searched for functions to +# export under their proper function names +# defaults to: none +# direct_export=di_dial;registrar_client +direct_export=sbc + +# run the XMLRPC server at all (default: yes) +# +# run_server=yes + +# timeout for client requests, in milliseconds (0 to disable) +# +# server_timeout=500 + +# print parameters of XMLRPC server calls into debug log [yes|no] +# debug_server_params=yes +# +# print result of XMLRPC server calls into debug log [yes|no] +# debug_server_result=yes +# diff --git a/pcscf/sems/sems.conf b/pcscf/sems/sems.conf new file mode 100644 index 0000000..ecae29e --- /dev/null +++ b/pcscf/sems/sems.conf @@ -0,0 +1,538 @@ +# $Id$ +# +# sems.conf.sample +# +# Sip Express Media Server (sems) +# +# sample configuration file +# +# +# whitespaces (spaces and tabs) are ignored +# comments start with a "#" and may be used inline +# +# example: option=value # i like this option +# +# @filename includes mod_config_path/filename +# @/absolute/path/to/file includes file + +############################################################ +# Network configuration + +# optional parameter: media_ip=| +# +# - this informs SEMS about the IP address or interface that +# SEMS uses to send and receive media. +# - If neither 'media_ip' nor 'sip_ip' are set, defaults +# to first non-loopback interface. If 'sip_ip' is set, +# 'media_ip' defaults to 'sip_ip. +# +# Examples: +# media_ip=10.0.0.34 +# media_ip=eth0 + +#media_ip=eth0 +media_ip=109.239.57.200 + +# optional parameter: sip_ip=| +# +# - this informs SEMS about the SIP IP where its SIP stack is +# bound to or should be bound to. This also sets +# the value used for contact header in outgoing calls and +# registrations. +# - If neither 'media_ip' nor 'sip_ip' are set, defaults +# to first non-loopback interface. If 'media_ip' is set, +# 'sip_ip' defaults to 'media_ip. +# +# Example: +# sip_ip=10.0.0.34 +# sip_ip=en0 +# + +sip_ip=127.0.0.1 + +# optional parameter: public_ip= +# +# - when running SEMS behind certain simple NAT configurations, +# you can use this parameter to inform SEMS of its public IP +# address. If this parameter is set, SEMS will write this value +# into SDP bodies. +# If this parameter is not set, the local IP address is used. +# N.B., there is no support for port translation; the local +# RTP port is advertised in SDP in either case. +# +# Example: +# public_ip=75.101.219.48 +# + +# optional parameter: sip_port= +# +# - this informs SEMS about the port where its SIP stack is +# bound to or should be bound to. SEMS needs this information +# to correctly set the contact header in outgoing calls +# and registrations. Should be set to equal the 'port' +# configuration option in ser_sems.cfg. +# +# default: 5060 +# +sip_port=5080 + +# optional parameter: outbound_proxy=uri +# +# - this sets an outbound proxy for calls and registrations initiated +# by SEMS. This does not apply to requests in a dialog that +# is initiated by someone else and incoming to SEMS. +# If this is not set (default setting), then for dialogs +# initiated by SEMS the r-uri is resolved and the request +# is sent there directly. +# This is resolved by the SIP stack with DNS if a name is given. +# Warning: If the value set here can not be resolved, no +# requests will be sent out at all! +# +# default: empty +# +# Example: +# outbound_proxy=sip:proxy.mydomain.net + +# optional parameter: force_outbound_proxy={yes|no} +# +# - forces SEMS to send any request to the outbound proxy in any +# situation, by adding an extra first Route to the outbound_proxy. +# This option will only have an effect if the outbound_proxy +# option has been set, and it will break 3261 compatibility +# in some cases; better use next_hop_ip/next_hop_port. +# +# default: no +# +# Example: +# force_outbound_proxy=yes + +# optional parameter: next_hop_ip +# - if this is set, all outgoing requests will be sent to +# this IP, regardless of R-URI etc. +# +#next_hop_ip=192.168.5.106 + +# optional parameter: next_hop_port +# defaults to 5060 +#next_hop_port=5060 + +# optional parameter:next_hop_for_replies +# - use next_hop for replies, too? +# +#next_hop_for_replies=yes + +# optional parameter: rtp_low_port= +# +# - sets lowest for RTP used port +rtp_low_port=10000 + +# optional parameter: rtp_high_port= +# +# - sets highest for RTP used port +rtp_high_port=19999 + +# Additional IFs (optional): +# additional_interfaces = +# +# additional_interfaces must be set if more than one +# interface is to be used for the same purpose (e.g. +# more than one interface for SIP). Configure additional +# interfaces if networks should be bridged or separate +# networks should be served. +# +# For each additional interface, a set of parameters +# suffixed with the interface name should be listed +# with the 'additional_interfaces' parameter. +# +# Please note that for each additional interface, +# 'sip_ip_[if_name]' is mandatory. The other +# parameters are optional. 'media_ip_[if_name]' +# is derived from 'sip_ip_[if_name]' if not set. +# 'public_ip_[ip_name]' is also based on 'sip_ip_[if_name]' +# if not set explicitly. +# +# Example: +# additional_interfaces=intern,extern +# +# sip_ip_intern=192.168.0.5 +# sip_port_intern=5060 +# media_ip_intern=192.168.10.5 +# rtp_low_port_intern=2000 +# rtp_high_port_intern=5000 +# +# sip_ip_extern=213.192.59.73 +# sip_port_extern=5060 +# media_ip_extern=213.192.59.73 +# rtp_low_port_extern=2000 +# rtp_high_port_extern=5000 +# public_ip_extern=213.192.35.73 +# + +############################################################ +# modules and application configuration +# +# Configuration of plugin (module) loading: +# - if load_plugins is set, only those are loaded. +# - if load_plugins is not set, all modules in the plugin_path +# directory are loaded, except those which are listed +# in exclude_plugins. +# + +# optional parameter: plugin_path= +# +# - sets the path to the plug-ins' binaries +# - may be absolute or relative to CWD +plugin_path=/usr/lib/sems/plug-in/ + +# optional parameter: load_plugins= +# +# semicolon-separated list of modules to load. +# If empty, all modules in plugin_path are loaded. +# +# example for announcement with only g711 and ilbc codecs +# load_plugins=wav;ilbc;announcement +load_plugins=wav;gsm;isac;ilbc;xmlrpc2di;monitoring;stats;uac_auth;session_timer;sbc + +# optional parameter: exclude_plugins= +# +# semicolon-separated list of modules to exclude from loading +# ('blacklist'). If empty, all modules in plugin_path are loaded. +# This has only effect it load_plugins is not set. +# +# o precoded_announce: no precoded sample files present +# o py_sems: conflicts with ivr (in some cases) +exclude_plugins=precoded_announce;py_sems + +# optional parameter: application +# +# This controls which application is to be executed if there +# is no explicit application requested from the SIP stack +# (i.e. unixsockctrl and second parameter of t_write_unix). +# +# This can be one of +# $(ruri.user) - user part of ruri is taken as application, +# e.g. sip:announcement@host +# $(ruri.param) - uri parameter "app", e.g. +# sip:joe@host.net;app=announcement +# $(apphdr) - the value of the P-App-Name header is used +# +# $(mapping) - regex=>application mapping is read from +# app_mapping.conf (see app_mapping.conf) +# - application name configured here, e.g. +# application=announcement +# +# examples: +# application = conference +# application = $(mapping) +# application = $(ruri.user) +# application = $(ruri.param) +application = sbc + +# parameter: plugin_config_path= +# +# - in this path configuration files of the applications +# (e.g. announcement.conf) are searched +plugin_config_path=/etc/sems/etc/ + +# optional parameter: exclude_payloads= +# +# semicolon-separated list of payloads to exclude from loading +# ('blacklist'). +# +# For example, to only use low bandwidth codecs: +# exclude_payloads=PCMU;PCMA;G726-40;G726-32;G721;L16 +# or, to use only codecs which are not CPU-intensive: +# exclude_payloads=iLBC;speex; +# only use G711 (exclude everything else): +# exclude_payloads=iLBC;speex;G726-40;G726-32;G721;G726-24;G726-16;GSM;L16 + +############################################################ +# logging and running + +# optional parameter: fork={yes|no} +# +# - specifies if sems should run in daemon mode (background) +# (fork=no is the same as -E) +fork=yes + +# optional parameter: stderr={yes|no} +# +# - debug mode: do not fork and log to stderr +# (stderr=yes is the same as -E) +stderr=no + +# optional parameter: loglevel={0|1|2|3} +# +# - sets log level (error=0, warning=1, info=2, debug=3) +# (same as -D) +loglevel=1 + +# optional parameter: syslog_facility={DAEMON|USER|LOCAL[0-7]} +# +# - sets the log facility that is used for syslog. Using this, +# the log can for example be filtered into a special file +# by the syslog daemon. +# +# Default: DAEMON +# +# Example: +# syslog_facility=LOCAL0 + +# optional parameter: log_sessions=[yes|no] +# +# Default: no +# +# If log_sessions=yes is set, INFO level log messages are generated +# for each session when it is started and stopped. +# +# log_sessions=yes + +# optional parameter: log_events=[yes|no] +# +# Default: no +# +# If log_eventy=yes is set, generic DBG level log messages are +# generated for each event that is posted into an event queue. +# +# log_events=yes + +# optional parameter: max_shutdown_time=