From 0b3f111928f7d898c6d99066f41a3a2e5f846904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marielena=20M=C3=A1rquez?= Date: Mon, 3 Oct 2022 11:08:45 +0200 Subject: [PATCH] Adds images for IMS deployment (#137) * Adds Kamailio IMS image * Adds DNS ancillary image for IMS deployment * Adds FHoSS ancillary image for IMS deployment * Adds Mysql ancillary image for IMS deployment * Adds OSMO ancillary images for IMS deployment * Adds Rtpengine ancillary image for IMS deployment * Adds instructions and files for IMS deployment * Fixes instructions for IMS deployment * Osmomsc, osmohlr and smsc moved to ims-sms branch * Updates rtpengine and new name for kamailio-ims * Updates image fhoss * Starts using mariadb official image * Starts using bind9 official image and static IPs * Deletes old images and adds image_info scripts * Updates tag in images Co-authored-by: mariel1105 --- docs/ims-open5gs-srsran/README.md | 27 + .../ims-open5gs-srsran/config/bind9/e164.arpa | 14 + docs/ims-open5gs-srsran/config/bind9/epc_zone | 13 + docs/ims-open5gs-srsran/config/bind9/ims_zone | 25 + .../config/bind9/named.conf | 48 + .../config/mariadb/custom-config.cnf | 9 + .../config/mariadb/entrypoint.sh | 12 + docs/ims-open5gs-srsran/config/mariadb/my.cnf | 3 + .../config/open5gs/entrypoint_open5gs.sh | 98 ++ .../config/open5gs/hss.conf | 266 ++++ .../config/open5gs/mme.yaml | 36 + .../config/open5gs/pcrf.conf | 268 ++++ .../config/open5gs/smf.conf | 265 ++++ .../config/open5gs/smf.yaml | 40 + .../config/open5gs/upf.yaml | 23 + .../ims-open5gs-srsran/config/srsran/enb.conf | 301 ++++ docs/ims-open5gs-srsran/config/srsran/rb.conf | 227 +++ docs/ims-open5gs-srsran/config/srsran/rr.conf | 94 ++ .../ims-open5gs-srsran/config/srsran/sib.conf | 176 +++ docs/ims-open5gs-srsran/docker-compose.yaml | 372 +++++ docs/ims-open5gs-srsran/srsenb.yaml | 33 + .../uhd_image_downloader.py | 639 +++++++++ images/fhoss/Dockerfile | 80 ++ images/fhoss/image_info.sh | 3 + images/fhoss/resources/DiameterPeerHSS.xml | 26 + images/fhoss/resources/configurator.sh | 28 + images/fhoss/resources/fhoss_init.sh | 122 ++ images/fhoss/resources/hibernate.properties | 21 + images/fhoss/resources/hss.sh | 18 + images/kamailio-ims/Dockerfile | 72 + images/kamailio-ims/icscf/icscf.cfg | 52 + images/kamailio-ims/icscf/icscf.xml | 34 + images/kamailio-ims/icscf/icscf_init.sh | 125 ++ images/kamailio-ims/icscf/kamailio_icscf.cfg | 639 +++++++++ images/kamailio-ims/image_info.sh | 3 + images/kamailio-ims/kamailio_init.sh | 51 + images/kamailio-ims/modules.lst | 24 + images/kamailio-ims/pcscf/dispatcher.list | 1 + images/kamailio-ims/pcscf/kamailio_pcscf.cfg | 997 +++++++++++++ images/kamailio-ims/pcscf/pcscf.cfg | 125 ++ images/kamailio-ims/pcscf/pcscf.xml | 26 + images/kamailio-ims/pcscf/pcscf_init.sh | 129 ++ images/kamailio-ims/pcscf/route/mo.cfg | 226 +++ images/kamailio-ims/pcscf/route/mt.cfg | 150 ++ images/kamailio-ims/pcscf/route/register.cfg | 318 ++++ images/kamailio-ims/pcscf/route/rtp.cfg | 208 +++ images/kamailio-ims/pcscf/route/websocket.cfg | 62 + images/kamailio-ims/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 + .../kamailio-ims/pcscf/sems/etc/rurimap.conf | 1 + images/kamailio-ims/pcscf/sems/etc/sbc.conf | 62 + images/kamailio-ims/pcscf/sems/etc/stats.conf | 5 + .../pcscf/sems/etc/xmlrpc2di.conf | 42 + images/kamailio-ims/pcscf/sems/sems.conf | 538 +++++++ images/kamailio-ims/pcscf/tls.cfg | 15 + images/kamailio-ims/scscf/CxDataType_Rel6.xsd | 293 ++++ images/kamailio-ims/scscf/CxDataType_Rel7.xsd | 301 ++++ images/kamailio-ims/scscf/CxDataType_Rel8.xsd | 379 +++++ images/kamailio-ims/scscf/dispatcher.list | 1 + images/kamailio-ims/scscf/kamailio_scscf.cfg | 1273 +++++++++++++++++ images/kamailio-ims/scscf/scscf.cfg | 84 ++ images/kamailio-ims/scscf/scscf.xml | 36 + images/kamailio-ims/scscf/scscf_init.sh | 112 ++ images/rtpengine/Dockerfile | 61 + images/rtpengine/image_info.sh | 3 + images/rtpengine/rtpengine_init.sh | 110 ++ 73 files changed, 10120 insertions(+) create mode 100644 docs/ims-open5gs-srsran/README.md create mode 100644 docs/ims-open5gs-srsran/config/bind9/e164.arpa create mode 100644 docs/ims-open5gs-srsran/config/bind9/epc_zone create mode 100644 docs/ims-open5gs-srsran/config/bind9/ims_zone create mode 100644 docs/ims-open5gs-srsran/config/bind9/named.conf create mode 100644 docs/ims-open5gs-srsran/config/mariadb/custom-config.cnf create mode 100644 docs/ims-open5gs-srsran/config/mariadb/entrypoint.sh create mode 100644 docs/ims-open5gs-srsran/config/mariadb/my.cnf create mode 100755 docs/ims-open5gs-srsran/config/open5gs/entrypoint_open5gs.sh create mode 100644 docs/ims-open5gs-srsran/config/open5gs/hss.conf create mode 100644 docs/ims-open5gs-srsran/config/open5gs/mme.yaml create mode 100644 docs/ims-open5gs-srsran/config/open5gs/pcrf.conf create mode 100644 docs/ims-open5gs-srsran/config/open5gs/smf.conf create mode 100644 docs/ims-open5gs-srsran/config/open5gs/smf.yaml create mode 100644 docs/ims-open5gs-srsran/config/open5gs/upf.yaml create mode 100644 docs/ims-open5gs-srsran/config/srsran/enb.conf create mode 100644 docs/ims-open5gs-srsran/config/srsran/rb.conf create mode 100644 docs/ims-open5gs-srsran/config/srsran/rr.conf create mode 100644 docs/ims-open5gs-srsran/config/srsran/sib.conf create mode 100644 docs/ims-open5gs-srsran/docker-compose.yaml create mode 100644 docs/ims-open5gs-srsran/srsenb.yaml create mode 100644 docs/ims-open5gs-srsran/uhd_image_downloader.py create mode 100644 images/fhoss/Dockerfile create mode 100644 images/fhoss/image_info.sh create mode 100644 images/fhoss/resources/DiameterPeerHSS.xml create mode 100755 images/fhoss/resources/configurator.sh create mode 100755 images/fhoss/resources/fhoss_init.sh create mode 100644 images/fhoss/resources/hibernate.properties create mode 100755 images/fhoss/resources/hss.sh create mode 100644 images/kamailio-ims/Dockerfile create mode 100644 images/kamailio-ims/icscf/icscf.cfg create mode 100644 images/kamailio-ims/icscf/icscf.xml create mode 100755 images/kamailio-ims/icscf/icscf_init.sh create mode 100644 images/kamailio-ims/icscf/kamailio_icscf.cfg create mode 100644 images/kamailio-ims/image_info.sh create mode 100755 images/kamailio-ims/kamailio_init.sh create mode 100644 images/kamailio-ims/modules.lst create mode 100644 images/kamailio-ims/pcscf/dispatcher.list create mode 100644 images/kamailio-ims/pcscf/kamailio_pcscf.cfg create mode 100644 images/kamailio-ims/pcscf/pcscf.cfg create mode 100644 images/kamailio-ims/pcscf/pcscf.xml create mode 100755 images/kamailio-ims/pcscf/pcscf_init.sh create mode 100644 images/kamailio-ims/pcscf/route/mo.cfg create mode 100644 images/kamailio-ims/pcscf/route/mt.cfg create mode 100644 images/kamailio-ims/pcscf/route/register.cfg create mode 100644 images/kamailio-ims/pcscf/route/rtp.cfg create mode 100644 images/kamailio-ims/pcscf/route/websocket.cfg create mode 100644 images/kamailio-ims/pcscf/route/xmlrpc.cfg create mode 100644 images/kamailio-ims/pcscf/sems/etc/methodmap.conf create mode 100644 images/kamailio-ims/pcscf/sems/etc/mo.sbcprofile.conf create mode 100644 images/kamailio-ims/pcscf/sems/etc/monitoring.conf create mode 100644 images/kamailio-ims/pcscf/sems/etc/mt.sbcprofile.conf create mode 100644 images/kamailio-ims/pcscf/sems/etc/nocache.sbcprofile.conf create mode 100644 images/kamailio-ims/pcscf/sems/etc/refuse.sbcprofile.conf create mode 100644 images/kamailio-ims/pcscf/sems/etc/refuse_with_200.sbcprofile.conf create mode 100644 images/kamailio-ims/pcscf/sems/etc/register.sbcprofile.conf create mode 100644 images/kamailio-ims/pcscf/sems/etc/rurimap.conf create mode 100644 images/kamailio-ims/pcscf/sems/etc/sbc.conf create mode 100644 images/kamailio-ims/pcscf/sems/etc/stats.conf create mode 100644 images/kamailio-ims/pcscf/sems/etc/xmlrpc2di.conf create mode 100644 images/kamailio-ims/pcscf/sems/sems.conf create mode 100644 images/kamailio-ims/pcscf/tls.cfg create mode 100644 images/kamailio-ims/scscf/CxDataType_Rel6.xsd create mode 100644 images/kamailio-ims/scscf/CxDataType_Rel7.xsd create mode 100644 images/kamailio-ims/scscf/CxDataType_Rel8.xsd create mode 100644 images/kamailio-ims/scscf/dispatcher.list create mode 100644 images/kamailio-ims/scscf/kamailio_scscf.cfg create mode 100644 images/kamailio-ims/scscf/scscf.cfg create mode 100644 images/kamailio-ims/scscf/scscf.xml create mode 100755 images/kamailio-ims/scscf/scscf_init.sh create mode 100644 images/rtpengine/Dockerfile create mode 100644 images/rtpengine/image_info.sh create mode 100755 images/rtpengine/rtpengine_init.sh diff --git a/docs/ims-open5gs-srsran/README.md b/docs/ims-open5gs-srsran/README.md new file mode 100644 index 0000000..9f02853 --- /dev/null +++ b/docs/ims-open5gs-srsran/README.md @@ -0,0 +1,27 @@ +# IMS + OPEN5GS + SRSRAN + +VoLTE demo with Kamailio IMS, Open5gs and srsRAN. + +Assuming SIMs have already been properly configured and using MNC 01 and MCC 001. + +# Deployment EPC and IMS components + +``` +docker-compose up -d +``` + +# Register subscribers + +Register both subscribers in Open5gs and FHoSS following the instructions provided in https://github.com/MAlexVR/docker_open5gs + +# Deployment RAN +Download the uhd_images folder using *uhd_image_downloader.py* script provided: +``` +python3 uhd_image_downloader.py -i uhd_images/ +``` + +Then: + +``` +docker-compose -f srsenb.yaml up -d +``` \ No newline at end of file diff --git a/docs/ims-open5gs-srsran/config/bind9/e164.arpa b/docs/ims-open5gs-srsran/config/bind9/e164.arpa new file mode 100644 index 0000000..16ce8a6 --- /dev/null +++ b/docs/ims-open5gs-srsran/config/bind9/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 172.22.0.15 + +; Wildcard to match any tel:+xxxx and change to sip:xxxx@ims.mnc001.mcc001.3gppnetwork.org +* IN NAPTR 10 100 "u" "E2U+sip" "!(^.*$)!sip:\\1@ims.mnc001.mcc001.3gppnetwork.org!" . +* IN NAPTR 20 100 "u" "E2U+sip" "!(^.*$)!sip:+\\1@ims.mnc001.mcc001.3gppnetwork.org!" . diff --git a/docs/ims-open5gs-srsran/config/bind9/epc_zone b/docs/ims-open5gs-srsran/config/bind9/epc_zone new file mode 100644 index 0000000..5bd45d9 --- /dev/null +++ b/docs/ims-open5gs-srsran/config/bind9/epc_zone @@ -0,0 +1,13 @@ +$ORIGIN openverso. +$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 172.22.0.15 + +pcrf 1D IN A 172.22.0.4 diff --git a/docs/ims-open5gs-srsran/config/bind9/ims_zone b/docs/ims-open5gs-srsran/config/bind9/ims_zone new file mode 100644 index 0000000..dd7a7ae --- /dev/null +++ b/docs/ims-open5gs-srsran/config/bind9/ims_zone @@ -0,0 +1,25 @@ +$ORIGIN ims.mnc001.mcc001.3gppnetwork.org. +$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 172.22.0.15 + +pcscf 1D IN A 172.22.0.21 +_sip._udp.pcscf 1D SRV 0 0 5060 pcscf +_sip._tcp.pcscf 1D SRV 0 0 5060 pcscf + +icscf 1D IN A 172.22.0.19 +_sip._udp 1D SRV 0 0 4060 icscf +_sip._tcp 1D SRV 0 0 4060 icscf + +scscf 1D IN A 172.22.0.20 +_sip._udp.scscf 1D SRV 0 0 6060 scscf +_sip._tcp.scscf 1D SRV 0 0 6060 scscf + +hss 1D IN A 172.22.0.18 \ No newline at end of file diff --git a/docs/ims-open5gs-srsran/config/bind9/named.conf b/docs/ims-open5gs-srsran/config/bind9/named.conf new file mode 100644 index 0000000..0846066 --- /dev/null +++ b/docs/ims-open5gs-srsran/config/bind9/named.conf @@ -0,0 +1,48 @@ +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.mnc001.mcc001.3gppnetwork.org" { + type master; + file "/etc/bind/ims_zone"; +}; + +zone "openverso" { + type master; + file "/etc/bind/epc_zone"; +}; + +zone "e164.arpa" { + type master; + file "/etc/bind/e164.arpa"; +}; diff --git a/docs/ims-open5gs-srsran/config/mariadb/custom-config.cnf b/docs/ims-open5gs-srsran/config/mariadb/custom-config.cnf new file mode 100644 index 0000000..d7f9d1a --- /dev/null +++ b/docs/ims-open5gs-srsran/config/mariadb/custom-config.cnf @@ -0,0 +1,9 @@ +[mysqld] +user = mysql +bind-address = 0.0.0.0 +# +# * Fine Tuning +# +key_buffer_size = 16M + +max_connections = 250 diff --git a/docs/ims-open5gs-srsran/config/mariadb/entrypoint.sh b/docs/ims-open5gs-srsran/config/mariadb/entrypoint.sh new file mode 100644 index 0000000..cb564c5 --- /dev/null +++ b/docs/ims-open5gs-srsran/config/mariadb/entrypoint.sh @@ -0,0 +1,12 @@ +ROOT_USER_EXISTS=`mysql -u root --password=${MARIADB_ROOT_PASSWORD} -s -N -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE User = 'root' AND Host = '%')"` +if [[ "$ROOT_USER_EXISTS" == 0 ]] +then + echo "Creating user 'root'@'%'" + mysql -u root -e "CREATE USER 'root'@'%' IDENTIFIED VIA mysql_native_password USING PASSWORD('${MARIADB_ROOT_PASSWORD}')"; +else + echo "User 'root'@'%' already exists..." +fi +# Grants privileges and sets blank password so FHoSS can access directly +mysql -u root --password=ims -e "GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION"; +mysql -u root --password=ims -e "ALTER USER 'root'@'%' IDENTIFIED VIA mysql_native_password USING PASSWORD('')" +mysql -u root --password=ims -e "FLUSH PRIVILEGES;" \ No newline at end of file diff --git a/docs/ims-open5gs-srsran/config/mariadb/my.cnf b/docs/ims-open5gs-srsran/config/mariadb/my.cnf new file mode 100644 index 0000000..3a2d7d5 --- /dev/null +++ b/docs/ims-open5gs-srsran/config/mariadb/my.cnf @@ -0,0 +1,3 @@ +[mysql] +user=root +password=ims \ No newline at end of file diff --git a/docs/ims-open5gs-srsran/config/open5gs/entrypoint_open5gs.sh b/docs/ims-open5gs-srsran/config/open5gs/entrypoint_open5gs.sh new file mode 100755 index 0000000..7c77c04 --- /dev/null +++ b/docs/ims-open5gs-srsran/config/open5gs/entrypoint_open5gs.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +set -eo pipefail + +# tun iface create +# function tun_create { +# if ! grep "ogstun" /proc/net/dev > /dev/null; then +# echo "Creating ogstun device" +# ip tuntap add name ogstun mode tun +# fi + +# ip addr del $IPV4_TUN_ADDR dev ogstun 2> /dev/null || true +# ip addr add $IPV4_TUN_ADDR dev ogstun; + +# sysctl -w net.ipv6.conf.all.disable_ipv6=0; +# ip addr del $IPV6_TUN_ADDR dev ogstun 2> /dev/null || true +# ip addr add $IPV6_TUN_ADDR dev ogstun + +# ip link set ogstun up +# sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"; +# if [ "$ENABLE_NAT" = true ] ; then +# iptables -t nat -A POSTROUTING -s $IPV4_TUN_SUBNET ! -o ogstun -j MASQUERADE; +# fi +# } + +function tun_create { + if ! grep "ogstun" /proc/net/dev > /dev/null; then + echo "Creating ogstun device" + ip tuntap add name ogstun mode tun + fi + + ip addr del 192.168.100.0/24 dev ogstun 2> /dev/null || true + ip addr add 192.168.100.0/24 dev ogstun; + + sysctl -w net.ipv6.conf.all.disable_ipv6=0; + ip addr del 2001:230:cafe::/48 dev ogstun 2> /dev/null || true + ip addr add 2001:230:cafe::/48 dev ogstun + + ip link set ogstun up + sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"; + iptables -t nat -A POSTROUTING -s 192.168.100.0/24 ! -o ogstun -j MASQUERADE; + + if ! grep "ogstun2" /proc/net/dev > /dev/null; then + echo "Creating ogstun2 device" + ip tuntap add name ogstun2 mode tun + fi + + ip addr del 192.168.101.0/24 dev ogstun2 2> /dev/null || true + ip addr add 192.168.101.0/24 dev ogstun2; + + sysctl -w net.ipv6.conf.all.disable_ipv6=0; + ip addr del 2001:230:babe::/48 dev ogstun2 2> /dev/null || true + ip addr add 2001:230:babe::/48 dev ogstun2 + + ip link set ogstun2 up + sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"; +} + +# Set extra environment variables +export MNC=01 +export MCC=001 +export PCSCF_HOSTNAME=pcscf + + COMMAND=$1 +if [[ "$COMMAND" == *"open5gs-pgwd" ]] || [[ "$COMMAND" == *"open5gs-upfd" ]]; then +echo "Running tun_if script" +tun_create +fi + +# Temporary patch to solve the case of docker internal dns not resolving "not running" container names. +# Just wait 10 seconds to be "running" and resolvable +if [[ "$COMMAND" == *"open5gs-pcrfd" ]] \ + || [[ "$COMMAND" == *"open5gs-mmed" ]] \ + || [[ "$COMMAND" == *"open5gs-sgwcd" ]] \ + || [[ "$COMMAND" == *"open5gs-upfd" ]]; then +sleep 10 +fi + +if [[ "$COMMAND" == *"open5gs-smfd" ]]; then +# Install extra packages needed +apt-get update && apt-get install -y dnsutils gettext-base + +PCSCF_IP=${PCSCF_IP:-"$(host -4 $PCSCF_HOSTNAME |awk '/has.*address/{print $NF; exit}')"} +export PCSCF_IP +echo "PCSCF_IP: $PCSCF_IP" + +if [[ -z "$PCSCF_IP" ]]; then +echo "Unable to resolve some IPs... restarting" +exit 1 +fi + +envsubst < /opt/open5gs/smf.yaml > /opt/open5gs/etc/open5gs/smf.yaml + +fi + +$@ + +exit 1 diff --git a/docs/ims-open5gs-srsran/config/open5gs/hss.conf b/docs/ims-open5gs-srsran/config/open5gs/hss.conf new file mode 100644 index 0000000..7ec11c9 --- /dev/null +++ b/docs/ims-open5gs-srsran/config/open5gs/hss.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 = "hss.openverso"; + +# The Diameter Realm of this daemon. +# Default: the domain part of Identity (after the first dot). +#Realm = "koganei.freediameter.net"; +Realm = "openverso"; + +############################################################## +## 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 = "127.0.0.4"; + + +############################################################## +## 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 = "etc/freeDiameter/hss.cert.pem", "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 = "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 = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dbg_msg_dumps.fdx" : "0x8888"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_rfc5777.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_mip6i.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_nasreq.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_nas_mipv6.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_dcca.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/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.openverso" { ConnectTo = "mme"; TcTimer = 60; TwTimer = 30; No_TLS; }; + +############################################################## diff --git a/docs/ims-open5gs-srsran/config/open5gs/mme.yaml b/docs/ims-open5gs-srsran/config/open5gs/mme.yaml new file mode 100644 index 0000000..58f41c7 --- /dev/null +++ b/docs/ims-open5gs-srsran/config/open5gs/mme.yaml @@ -0,0 +1,36 @@ +mme: + freeDiameter: mme.conf + s1ap: + gtpc: + gummei: + plmn_id: + mcc: 001 + mnc: 01 + mme_gid: 2 + mme_code: 1 + tai: + plmn_id: + mcc: 001 + mnc: 01 + tac: 1 + security: + integrity_order : [ EIA2, EIA1, EIA0 ] + ciphering_order : [ EEA0, EEA1, EEA2 ] + network_name: + full: Openverso + mme_name: open5gs-mme0 + +sgwc: + gtpc: + - name: sgwc +smf: + gtpc: + - name: smf + +parameter: + +max: + +pool: + +sctp: \ No newline at end of file diff --git a/docs/ims-open5gs-srsran/config/open5gs/pcrf.conf b/docs/ims-open5gs-srsran/config/open5gs/pcrf.conf new file mode 100644 index 0000000..0e52067 --- /dev/null +++ b/docs/ims-open5gs-srsran/config/open5gs/pcrf.conf @@ -0,0 +1,268 @@ +# 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.openverso"; + +# The Diameter Realm of this daemon. +# Default: the domain part of Identity (after the first dot). +#Realm = "koganei.freediameter.net"; +Realm = "openverso"; + +############################################################## +## 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 = "127.0.0.5"; + + +############################################################## +## 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 = "etc/freeDiameter/pcrf.cert.pem", "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 = "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 = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dbg_msg_dumps.fdx" : "0x8888"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_rfc5777.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_mip6i.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_nasreq.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_nas_mipv6.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_dcca.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/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.openverso" { ConnectTo = "smf"; TcTimer = 60; TwTimer = 30; No_TLS; }; +ConnectPeer = "pcscf.ims.mnc001.mcc001.3gppnetwork.org" { ConnectTo = "pcscf"; Port = 3871; No_TLS; }; + +############################################################## diff --git a/docs/ims-open5gs-srsran/config/open5gs/smf.conf b/docs/ims-open5gs-srsran/config/open5gs/smf.conf new file mode 100644 index 0000000..a1924da --- /dev/null +++ b/docs/ims-open5gs-srsran/config/open5gs/smf.conf @@ -0,0 +1,265 @@ +# 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 = "smf.openverso"; + +# The Diameter Realm of this daemon. +# Default: the domain part of Identity (after the first dot). +#Realm = "koganei.freediameter.net"; +Realm = "openverso"; + +############################################################## +## 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 = "127.0.0.3"; + + +############################################################## +## 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 = "etc/freeDiameter/smf.cert.pem", "etc/freeDiameter/smf.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 = "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 = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dbg_msg_dumps.fdx" : "0x8888"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_rfc5777.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_mip6i.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_nasreq.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_nas_mipv6.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/freeDiameter/dict_dcca.fdx"; +LoadExtension = "/usr/local/lib/x86_64-linux-gnu/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 = "pcrf.openverso" { ConnectTo = "pcrf"; TcTimer = 60; TwTimer = 30; No_TLS; }; + +############################################################## diff --git a/docs/ims-open5gs-srsran/config/open5gs/smf.yaml b/docs/ims-open5gs-srsran/config/open5gs/smf.yaml new file mode 100644 index 0000000..09d43f0 --- /dev/null +++ b/docs/ims-open5gs-srsran/config/open5gs/smf.yaml @@ -0,0 +1,40 @@ +### For reference, see `/opt/open5gs/etc/orig/open5gs/` +smf: + sbi: + - dev: eth0 + advertise: smf + gtpc: + gtpu: + pfcp: + subnet: + - addr: 192.168.100.1/24 + dnn: internet + dev: ogstun + - addr: 2001:230:cafe::1/48 + dev: ogstun + dnn: internet + - addr: 192.168.101.1/24 + dnn: ims + dev: ogstun2 + - addr: 2001:230:babe::1/48 + dnn: ims + dev: ogstun2 + + dns: + - 8.8.8.8 + - 8.8.4.4 + - 2001:4860:4860::8888 + - 2001:4860:4860::8844 + mtu: 1400 + p-cscf: + - ${PCSCF_IP} + freeDiameter: smf.conf + +upf: + pfcp: + - name: upf + +parameter: +max: +pool: +time: diff --git a/docs/ims-open5gs-srsran/config/open5gs/upf.yaml b/docs/ims-open5gs-srsran/config/open5gs/upf.yaml new file mode 100644 index 0000000..98510bb --- /dev/null +++ b/docs/ims-open5gs-srsran/config/open5gs/upf.yaml @@ -0,0 +1,23 @@ +upf: + pfcp: + gtpu: + subnet: + - addr: 192.168.100.1/24 + dev: ogstun + dnn: internet + - addr: 2001:230:cafe::1/48 + dev: ogstun + dnn: internet + - addr: 192.168.101.1/24 + dnn: ims + dev: ogstun2 + - addr: 2001:230:babe::1/48 + dnn: ims + dev: ogstun2 + +smf: + pfcp: + - name: smf +parameter: +max: +pool: diff --git a/docs/ims-open5gs-srsran/config/srsran/enb.conf b/docs/ims-open5gs-srsran/config/srsran/enb.conf new file mode 100644 index 0000000..a8654ac --- /dev/null +++ b/docs/ims-open5gs-srsran/config/srsran/enb.conf @@ -0,0 +1,301 @@ +##################################################################### +# srsENB configuration file +##################################################################### + +##################################################################### +# eNB configuration +# +# enb_id: 20-bit eNB identifier. +# mcc: Mobile Country Code +# mnc: Mobile Network Code +# mme_addr: IP address of MME for S1 connnection +# gtp_bind_addr: Local IP address to bind for GTP connection +# s1c_bind_addr: Local IP address to bind for S1AP connection +# n_prb: Number of Physical Resource Blocks (6,15,25,50,75,100) +# tm: Transmission mode 1-4 (TM1 default) +# nof_ports: Number of Tx ports (1 port default, set to 2 for TM2/3/4) +# +##################################################################### +[enb] +enb_id = ${ENB_ID} +mcc = ${MCC} +mnc = ${MNC} +mme_addr = ${MME_ADDR} +gtp_bind_addr = ${GTP_BIND_ADDR} +s1c_bind_addr = ${S1C_BIND_ADDR} +n_prb = 50 +#tm = 4 +#nof_ports = 2 + +##################################################################### +# eNB configuration files +# +# sib_config: SIB1, SIB2 and SIB3 configuration file +# note: when enabling mbms, use the sib.conf.mbsfn configuration file which includes SIB13 +# rr_config: Radio Resources configuration file +# drb_config: DRB configuration file +##################################################################### +[enb_files] +sib_config = sib.conf +rr_config = rr.conf +rb_config = rb.conf + +##################################################################### +# RF configuration +# +# dl_earfcn: EARFCN code for DL (only valid if a single cell is configured in rr.conf) +# tx_gain: Transmit gain (dB). +# rx_gain: Optional receive gain (dB). If disabled, AGC if enabled +# +# Optional parameters: +# dl_freq: Override DL frequency corresponding to dl_earfcn +# ul_freq: Override UL frequency corresponding to dl_earfcn (must be set if dl_freq is set) +# device_name: Device driver family. +# Supported options: "auto" (uses first found), "UHD", "bladeRF", "soapy" or "zmq". +# device_args: Arguments for the device driver. Options are "auto" or any string. +# Default for UHD: "recv_frame_size=9232,send_frame_size=9232" +# Default for bladeRF: "" +# time_adv_nsamples: Transmission time advance (in number of samples) to compensate for RF delay +# from antenna to timestamp insertion. +# Default "auto". B210 USRP: 100 samples, bladeRF: 27. +##################################################################### +[rf] +#dl_earfcn = 3350 +tx_gain = 80 +rx_gain = 40 + +#device_name = auto + +# For best performance in 2x2 MIMO and >= 15 MHz use the following device_args settings: +# USRP B210: num_recv_frames=64,num_send_frames=64 +# And for 75 PRBs, also append ",master_clock_rate=15.36e6" to the device args + +# For best performance when BW<5 MHz (25 PRB), use the following device_args settings: +# USRP B210: send_frame_size=512,recv_frame_size=512 + +#device_args = auto +#time_adv_nsamples = auto + +# Example for ZMQ-based operation with TCP transport for I/Q samples +#device_name = zmq +#device_args = fail_on_disconnect=true,tx_port=tcp://*:2000,rx_port=tcp://localhost:2001,id=enb,base_srate=23.04e6 + +##################################################################### +# Packet capture configuration +# +# MAC Packets are captured to file in the compact format decoded by +# the Wireshark mac-lte-framed dissector and with DLT 147. +# To use the dissector, edit the preferences for DLT_USER to +# add an entry with DLT=147, Payload Protocol=mac-lte-framed. +# For more information see: https://wiki.wireshark.org/MAC-LTE +# +# Please note that this setting will by default only capture MAC +# frames on dedicated channels, and not SIB. You have to build with +# WRITE_SIB_PCAP enabled in srsenb/src/stack/mac/mac.cc if you want +# SIB to be part of the MAC pcap file. +# +# S1AP Packets are captured to file in the compact format decoded by +# the Wireshark s1ap dissector and with DLT 150. +# To use the dissector, edit the preferences for DLT_USER to +# add an entry with DLT=150, Payload Protocol=s1ap. +# +# mac_enable: Enable MAC layer packet captures (true/false) +# mac_filename: File path to use for packet captures +# s1ap_enable: Enable or disable the PCAP. +# s1ap_filename: File name where to save the PCAP. +# +##################################################################### +[pcap] +enable = false +filename = /tmp/enb.pcap +s1ap_enable = false +s1ap_filename = /tmp/enb_s1ap.pcap + +##################################################################### +# Log configuration +# +# Log levels can be set for individual layers. "all_level" sets log +# level for all layers unless otherwise configured. +# Format: e.g. phy_level = info +# +# In the same way, packet hex dumps can be limited for each level. +# "all_hex_limit" sets the hex limit for all layers unless otherwise +# configured. +# Format: e.g. phy_hex_limit = 32 +# +# Logging layers: rf, phy, phy_lib, mac, rlc, pdcp, rrc, gtpu, s1ap, stack, all +# Logging levels: debug, info, warning, error, none +# +# filename: File path to use for log output. Can be set to stdout +# to print logs to standard output +# file_max_size: Maximum file size (in kilobytes). When passed, multiple files are created. +# If set to negative, a single log file will be created. +##################################################################### +[log] +all_level = warning +all_hex_limit = 32 +filename = /tmp/enb.log +file_max_size = -1 + +[gui] +enable = false + +##################################################################### +# Scheduler configuration options +# +# max_aggr_level: Optional maximum aggregation level index (l=log2(L) can be 0, 1, 2 or 3) +# pdsch_mcs: Optional fixed PDSCH MCS (ignores reported CQIs if specified) +# pdsch_max_mcs: Optional PDSCH MCS limit +# pusch_mcs: Optional fixed PUSCH MCS (ignores reported CQIs if specified) +# pusch_max_mcs: Optional PUSCH MCS limit +# min_nof_ctrl_symbols: Minimum number of control symbols +# max_nof_ctrl_symbols: Maximum number of control symbols +# +##################################################################### +[scheduler] +#max_aggr_level = -1 +#pdsch_mcs = -1 +#pdsch_max_mcs = -1 +#pusch_mcs = -1 +#pusch_max_mcs = 16 +#min_nof_ctrl_symbols = 1 +#max_nof_ctrl_symbols = 3 +nr_pdsch_mcs=28 + +##################################################################### +# eMBMS configuration options +# +# enable: Enable MBMS transmission in the eNB +# m1u_multiaddr: Multicast addres the M1-U socket will register to +# m1u_if_addr: Address of the inteferface the M1-U interface will listen for multicast packets. +# mcs: Modulation and Coding scheme for MBMS traffic. +# +##################################################################### +[embms] +#enable = false +#m1u_multiaddr = 239.255.0.1 +#m1u_if_addr = 127.0.1.201 +#mcs = 20 + + + +##################################################################### +# Channel emulator options: +# enable: Enable/Disable internal Downlink/Uplink channel emulator +# +# -- AWGN Generator +# awgn.enable: Enable/disable AWGN generator +# awgn.snr: Target SNR in dB +# +# -- Fading emulator +# fading.enable: Enable/disable fading simulator +# fading.model: Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc) +# +# -- Delay Emulator delay(t) = delay_min + (delay_max - delay_min) * (1 + sin(2pi*t/period)) / 2 +# Maximum speed [m/s]: (delay_max - delay_min) * pi * 300 / period +# delay.enable: Enable/disable delay simulator +# delay.period_s: Delay period in seconds. +# delay.init_time_s: Delay initial time in seconds. +# delay.maximum_us: Maximum delay in microseconds +# delay.minumum_us: Minimum delay in microseconds +# +# -- Radio-Link Failure (RLF) Emulator +# rlf.enable: Enable/disable RLF simulator +# rlf.t_on_ms: Time for On state of the channel (ms) +# rlf.t_off_ms: Time for Off state of the channel (ms) +# +# -- High Speed Train Doppler model simulator +# hst.enable: Enable/Disable HST simulator +# hst.period_s: HST simulation period in seconds +# hst.fd_hz: Doppler frequency in Hz +# hst.init_time_s: Initial time in seconds +##################################################################### +[channel.dl] +#enable = false + +[channel.dl.awgn] +#enable = false +#snr = 30 + +[channel.dl.fading] +#enable = false +#model = none + +[channel.dl.delay] +#enable = false +#period_s = 3600 +#init_time_s = 0 +#maximum_us = 100 +#minimum_us = 10 + +[channel.dl.rlf] +#enable = false +#t_on_ms = 10000 +#t_off_ms = 2000 + +[channel.dl.hst] +#enable = false +#period_s = 7.2 +#fd_hz = 750.0 +#init_time_s = 0.0 + +[channel.ul] +#enable = false + +[channel.ul.awgn] +#enable = false +#n0 = -30 + +[channel.ul.fading] +#enable = false +#model = none + +[channel.ul.delay] +#enable = false +#period_s = 3600 +#init_time_s = 0 +#maximum_us = 100 +#minimum_us = 10 + +[channel.ul.rlf] +#enable = false +#t_on_ms = 10000 +#t_off_ms = 2000 + +[channel.ul.hst] +#enable = false +#period_s = 7.2 +#fd_hz = -750.0 +#init_time_s = 0.0 + + +##################################################################### +# Expert configuration options +# +# pusch_max_its: Maximum number of turbo decoder iterations (Default 4) +# pusch_8bit_decoder: Use 8-bit for LLR representation and turbo decoder trellis computation (Experimental) +# nof_phy_threads: Selects the number of PHY threads (maximum 4, minimum 1, default 3) +# metrics_period_secs: Sets the period at which metrics are requested from the eNB. +# metrics_csv_enable: Write eNB metrics to CSV file. +# metrics_csv_filename: File path to use for CSV metrics. +# pregenerate_signals: Pregenerate uplink signals after attach. Improves CPU performance. +# tx_amplitude: Transmit amplitude factor (set 0-1 to reduce PAPR) +# rrc_inactivity_timer Inactivity timeout used to remove UE context from RRC (in milliseconds). +# max_prach_offset_us: Maximum allowed RACH offset (in us) +# eea_pref_list: Ordered preference list for the selection of encryption algorithm (EEA) (default: EEA0, EEA2, EEA1). +# eia_pref_list: Ordered preference list for the selection of integrity algorithm (EIA) (default: EIA2, EIA1, EIA0). +# +##################################################################### +[expert] +#pusch_max_its = 8 # These are half iterations +#pusch_8bit_decoder = false +#nof_phy_threads = 3 +#metrics_period_secs = 1 +#metrics_csv_enable = false +#metrics_csv_filename = /tmp/enb_metrics.csv +#pregenerate_signals = false +#tx_amplitude = 0.6 +#rrc_inactivity_timer = 30000 +#max_prach_offset_us = 30 +#eea_pref_list = EEA0, EEA2, EEA1 +#eia_pref_list = EIA2, EIA1, EIA0 diff --git a/docs/ims-open5gs-srsran/config/srsran/rb.conf b/docs/ims-open5gs-srsran/config/srsran/rb.conf new file mode 100644 index 0000000..6a64d3c --- /dev/null +++ b/docs/ims-open5gs-srsran/config/srsran/rb.conf @@ -0,0 +1,227 @@ +// All times are in ms. Use -1 for infinity, where available + +// 4G Section + +// srb1_config = { +// rlc_config = { +// ul_am = { +// t_poll_retx = 45; +// poll_pdu = -1; +// poll_byte = -1; +// max_retx_thresh = 4; +// }; +// dl_am = { +// t_reordering = 35; +// t_status_prohibit = 0; +// }; +// enb_specific = { +// dl_max_retx_thresh = 32; +// }; +// }; +// } + +// srb2_config = { +// rlc_config = { +// ul_am = { +// t_poll_retx = 45; +// poll_pdu = -1; +// poll_byte = -1; +// max_retx_thresh = 4; +// }; +// dl_am = { +// t_reordering = 35; +// t_status_prohibit = 0; +// }; +// enb_specific = { +// dl_max_retx_thresh = 32; +// }; +// }; +// } + +qci_config = ( +{ + qci=1; + pdcp_config = { + discard_timer = 100; + pdcp_sn_size = 12; + } + rlc_config = { + ul_um = { + sn_field_length = 10; + }; + dl_um = { + sn_field_length = 10; + t_reordering = 50; + }; + }; + logical_channel_config = { + priority = 6; + prioritized_bit_rate = -1; + bucket_size_duration = 100; + log_chan_group = 1; + }; + enb_specific = { + dl_max_retx_thresh = 32; + }; +}, +{ + qci=2; + pdcp_config = { + discard_timer = 100; + pdcp_sn_size = 12; + } + rlc_config = { + ul_um = { + sn_field_length = 10; + }; + dl_um = { + sn_field_length = 10; + t_reordering = 50; + }; + }; + logical_channel_config = { + priority = 4; + prioritized_bit_rate = -1; + bucket_size_duration = 100; + log_chan_group = 1; + }; + enb_specific = { + dl_max_retx_thresh = 32; + }; +}, +{ + qci=5; + pdcp_config = { + discard_timer = -1; + status_report_required = true; + } + rlc_config = { + ul_am = { + t_poll_retx = 80; + poll_pdu = 128; + poll_byte = 125; + max_retx_thresh = 4; + }; + dl_am = { + t_reordering = 80; + t_status_prohibit = 60; + }; + }; + logical_channel_config = { + priority = 13; + prioritized_bit_rate = -1; + bucket_size_duration = 100; + log_chan_group = 2; + }; + enb_specific = { + dl_max_retx_thresh = 32; + }; +}, +{ + qci = 7; + pdcp_config = { + discard_timer = 100; + pdcp_sn_size = 12; + } + rlc_config = { + ul_um = { + sn_field_length = 10; + }; + dl_um = { + sn_field_length = 10; + t_reordering = 45; + }; + }; + logical_channel_config = { + priority = 13; + prioritized_bit_rate = -1; + bucket_size_duration = 100; + log_chan_group = 2; + }; + enb_specific = { + dl_max_retx_thresh = 32; + }; +}, +{ + qci = 9; + pdcp_config = { + discard_timer = -1; + status_report_required = true; + } + rlc_config = { + ul_am = { + t_poll_retx = 120; + poll_pdu = 64; + poll_byte = 750; + max_retx_thresh = 16; + }; + dl_am = { + t_reordering = 50; + t_status_prohibit = 50; + }; + }; + logical_channel_config = { + priority = 11; + prioritized_bit_rate = -1; + bucket_size_duration = 100; + log_chan_group = 3; + }; + enb_specific = { + dl_max_retx_thresh = 32; + }; +} +); + +// 5G Section +five_qi_config = ( +{ + five_qi = 7; + pdcp_nr_config = { + drb = { + discard_timer = 50; + pdcp_sn_size_ul = 18; + pdcp_sn_size_dl = 18; + }; + t_reordering = 50; + }; + rlc_config = { + um_bi_dir = { + ul_um = { + sn_field_len = 12; + }; + dl_um = { + sn_field_len = 12; + t_reassembly = 50; + }; + }; + }; +}, +{ + five_qi = 9; + pdcp_nr_config = { + drb = { + discard_timer = 50; + pdcp_sn_size_ul = 18; + pdcp_sn_size_dl = 18; + }; + t_reordering = 50; + }; + rlc_config = { + am = { + ul_am = { + sn_field_len = 12; + t_poll_retx = 50; + poll_pdu = 4; + poll_byte = 3000; + max_retx_thres = 4; + }; + dl_am = { + sn_field_len = 12; + t_reassembly = 50; + t_status_prohibit = 50; + }; + }; + }; +} +); + diff --git a/docs/ims-open5gs-srsran/config/srsran/rr.conf b/docs/ims-open5gs-srsran/config/srsran/rr.conf new file mode 100644 index 0000000..ccf2fb3 --- /dev/null +++ b/docs/ims-open5gs-srsran/config/srsran/rr.conf @@ -0,0 +1,94 @@ +mac_cnfg = +{ + phr_cnfg = + { + dl_pathloss_change = "dB3"; // Valid: 1, 3, 6 or INFINITY + periodic_phr_timer = 50; + prohibit_phr_timer = 0; + }; + ulsch_cnfg = + { + max_harq_tx = 4; + periodic_bsr_timer = 20; // in ms + retx_bsr_timer = 320; // in ms + }; + + time_alignment_timer = -1; // -1 is infinity +}; + +phy_cnfg = +{ + phich_cnfg = + { + duration = "Normal"; + resources = "1/6"; + }; + + pusch_cnfg_ded = + { + beta_offset_ack_idx = 6; + beta_offset_ri_idx = 6; + beta_offset_cqi_idx = 6; + }; + + // PUCCH-SR resources are scheduled on time-frequeny domain first, then multiplexed in the same resource. + sched_request_cnfg = + { + dsr_trans_max = 64; + period = 20; // in ms + //subframe = [1, 11]; // Optional vector of subframe indices allowed for SR transmissions (default uses all) + nof_prb = 1; // number of PRBs on each extreme used for SR (total prb is twice this number) + }; + cqi_report_cnfg = + { + mode = "periodic"; + simultaneousAckCQI = true; + period = 40; // in ms + //subframe = [0, 10, 20, 30]; // Optional vector of subframe indices every period where CQI resources will be allocated (default uses all) + m_ri = 8; // RI period in CQI period + }; +}; + +cell_list = +( + { + // rf_port = 0; + cell_id = 0x01; + tac = 0x${TAC}; + pci = 1; + // root_seq_idx = 204; + dl_earfcn = 3150; + //ul_earfcn = 21400; + ho_active = false; + + // CA cells + scell_list = ( + // {cell_id = 0x02; cross_carrier_scheduling = false; scheduling_cell_id = 0x02; ul_allowed = true} + ) + + // Cells available for handover + meas_cell_list = + ( + { + eci = 0x19C02; + dl_earfcn = 2850; + pci = 2; + } + ); + + // ReportCfg (only A3 supported) + meas_report_desc = { + a3_report_type = "RSRP"; + a3_offset = 6; + a3_hysteresis = 0; + a3_time_to_trigger = 480; + rsrq_config = 4; + }; + } + // Add here more cells +); + +nr_cell_list = +( + // no NR cells +); diff --git a/docs/ims-open5gs-srsran/config/srsran/sib.conf b/docs/ims-open5gs-srsran/config/srsran/sib.conf new file mode 100644 index 0000000..9ecf9b8 --- /dev/null +++ b/docs/ims-open5gs-srsran/config/srsran/sib.conf @@ -0,0 +1,176 @@ +sib1 = +{ + intra_freq_reselection = "Allowed"; + q_rx_lev_min = -65; + //p_max = 3; + cell_barred = "NotBarred" + si_window_length = 20; + sched_info = + ( + { + si_periodicity = 16; + + // comma-separated array of SIB-indexes (from 3 to 13), leave empty or commented to just scheduler sib2 + si_mapping_info = [ 3 ]; + } + ); + system_info_value_tag = 0; +}; + +sib2 = +{ + rr_config_common_sib = + { + rach_cnfg = + { + num_ra_preambles = 52; + preamble_init_rx_target_pwr = -104; + pwr_ramping_step = 6; // in dB + preamble_trans_max = 10; + ra_resp_win_size = 10; // in ms + mac_con_res_timer = 64; // in ms + max_harq_msg3_tx = 4; + }; + bcch_cnfg = + { + modification_period_coeff = 16; // in ms + }; + pcch_cnfg = + { + default_paging_cycle = 32; // in rf + nB = "1"; + }; + prach_cnfg = + { + root_sequence_index = 128; + prach_cnfg_info = + { + high_speed_flag = false; + prach_config_index = 3; + prach_freq_offset = 2; + zero_correlation_zone_config = 5; + }; + }; + pdsch_cnfg = + { + /* Warning: Currently disabled and forced to p_b=1 for TM2/3/4 and p_b=0 for TM1 + */ + p_b = 1; + rs_power = 0; + }; + pusch_cnfg = + { + n_sb = 1; + hopping_mode = "inter-subframe"; + pusch_hopping_offset = 2; + enable_64_qam = false; // 64QAM PUSCH is not currently enabled + ul_rs = + { + cyclic_shift = 0; + group_assignment_pusch = 0; + group_hopping_enabled = false; + sequence_hopping_enabled = false; + }; + }; + pucch_cnfg = + { + delta_pucch_shift = 1; + n_rb_cqi = 1; + n_cs_an = 0; + n1_pucch_an = 12; + }; + ul_pwr_ctrl = + { + p0_nominal_pusch = -85; + alpha = 0.7; + p0_nominal_pucch = -107; + delta_flist_pucch = + { + format_1 = 0; + format_1b = 3; + format_2 = 1; + format_2a = 2; + format_2b = 2; + }; + delta_preamble_msg3 = 6; + }; + ul_cp_length = "len1"; + }; + + ue_timers_and_constants = + { + t300 = 2000; // in ms + t301 = 100; // in ms + t310 = 200; // in ms + n310 = 1; + t311 = 10000; // in ms + n311 = 1; + }; + + freqInfo = + { + ul_carrier_freq_present = true; + ul_bw_present = true; + additional_spectrum_emission = 1; + }; + + time_alignment_timer = "INFINITY"; // use "sf500", "sf750", etc. +}; + +sib3 = +{ + cell_reselection_common = { + q_hyst = 2; // in dB + }, + cell_reselection_serving = { + s_non_intra_search = 3, + thresh_serving_low = 2, + cell_resel_prio = 6 + }, + intra_freq_reselection = { + q_rx_lev_min = -61, + p_max = 23, + s_intra_search = 5, + presence_ant_port_1 = true, + neigh_cell_cnfg = 1, + t_resel_eutra = 1 + } +}; + +##################################################################### +# sib7 configuration options (See TS 36.331) +# Contains GERAN neighbor information for CSFB and inter-rat handover. +# Must be added to sib1::sched_info::si_mapping_info array parameter to be transmitted +# +# t_resel_geran: Cell reselection timer (seconds) +# carrier_freqs_info_list: A list of carrier frequency groups. +# cell_resel_prio: Absolute priority of the carrier frequency group +# ncc_permitted: 8-bit bitmap of NCC carriers permitted for monitoring +# q_rx_lev_min: Minimum receive level in gsm cell, ([field_val] * 2) - 115 = [level in dBm] +# thresh_x_high: Srclev threshold (dB) to select to a higher-priority RAT/Frequency +# thresh_x_low: Srclev threshold (dB) to select to a lower-priority RAT/Frequency +# start_arfcn: Initial search ARFCN value +# band_ind: One of "dcs1800" or "pcs1900" Disambiguates ARFCNs in these bands, has no meaning for other ARFCNs. +# explicit_list_of_arfcns: List of ARFCN numbers in the group +# +##################################################################### +sib7 = +{ + t_resel_geran = 1; + carrier_freqs_info_list = + ( + { + cell_resel_prio = 0; + ncc_permitted = 255; + q_rx_lev_min = 0; + thresh_x_high = 2; + thresh_x_low = 2; + + start_arfcn = 871; + band_ind = "dcs1800"; + explicit_list_of_arfcns = ( + 871 + ); + } + ); +}; diff --git a/docs/ims-open5gs-srsran/docker-compose.yaml b/docs/ims-open5gs-srsran/docker-compose.yaml new file mode 100644 index 0000000..7f5d8cb --- /dev/null +++ b/docs/ims-open5gs-srsran/docker-compose.yaml @@ -0,0 +1,372 @@ +version: "3" +services: + mongo: + image: mongo:4.4.13 + environment: + MONGO_INITDB_DATABASE: open5gs + container_name: mongo + volumes: + - mongodbdata:/data/db + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "27017/udp" + - "27017/tcp" + command: mongod --bind_ip 0.0.0.0 + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.2 + webui: + image: openverso/open5gs-webui:2.4.9 + container_name: webui + depends_on: + - mongo + environment: + - DB_URI=mongodb://mongo/open5gs + - NODE_ENV=dev + volumes: + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3000/tcp" + ports: + - "3000:3000/tcp" + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.26 + hss: + image: openverso/open5gs:2.4.9 + entrypoint: /entrypoint_open5gs.sh + container_name: hss + command: open5gs-hssd + volumes: + - ./config/open5gs/entrypoint_open5gs.sh:/entrypoint_open5gs.sh + - ./config/open5gs/hss.conf:/opt/open5gs/etc/freeDiameter/hss.conf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + depends_on: + - mongo + environment: + - DB_URI=mongodb://mongo/open5gs + expose: + - "3868/udp" + - "3868/tcp" + - "3868/sctp" + - "5868/udp" + - "5868/tcp" + - "5868/sctp" + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.3 + sgwc: + image: openverso/open5gs:2.4.9 + entrypoint: /entrypoint_open5gs.sh + command: open5gs-sgwcd + depends_on: + - smf + - upf + container_name: sgwc + volumes: + - ./config/open5gs/entrypoint_open5gs.sh:/entrypoint_open5gs.sh + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2123/udp" + - "8805/udp" + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.5 + sgwu: + image: openverso/open5gs:2.4.9 + entrypoint: /entrypoint_open5gs.sh + command: open5gs-sgwud + depends_on: + - smf + - upf + container_name: sgwu + volumes: + - ./config/open5gs/entrypoint_open5gs.sh:/entrypoint_open5gs.sh + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "8805/udp" + - "2152/udp" + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.6 + smf: + image: openverso/open5gs:2.4.9 + entrypoint: /entrypoint_open5gs.sh + command: open5gs-smfd + container_name: smf + volumes: + - ./config/open5gs/entrypoint_open5gs.sh:/entrypoint_open5gs.sh + - ./config/open5gs/smf.conf:/opt/open5gs/etc/freeDiameter/smf.conf + - ./config/open5gs/smf.yaml:/opt/open5gs/smf.yaml + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/udp" + - "3868/tcp" + - "3868/sctp" + - "5868/udp" + - "5868/tcp" + - "5868/sctp" + - "8805/udp" + - "2123/udp" + - "7777/tcp" + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.7 + upf: + image: openverso/open5gs:2.4.9 + entrypoint: /entrypoint_open5gs.sh + command: open5gs-upfd + depends_on: + - smf + container_name: upf + volumes: + - ./config/open5gs/entrypoint_open5gs.sh:/entrypoint_open5gs.sh + - ./config/open5gs/upf.yaml:/opt/open5gs/etc/open5gs/upf.yaml + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "2152/udp" + - "8805/udp" + ports: + - 2152:2152 + cap_add: + - all + privileged: true + sysctls: + - net.ipv4.ip_forward=1 + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.8 + mme: + image: openverso/open5gs:2.4.9 + entrypoint: /entrypoint_open5gs.sh + command: open5gs-mmed + depends_on: + - hss + - sgwc + - sgwu + - smf + - upf + container_name: mme + volumes: + - ./config/open5gs/entrypoint_open5gs.sh:/entrypoint_open5gs.sh + - ./config/open5gs/mme.yaml:/opt/open5gs/etc/open5gs/mme.yaml + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/udp" + - "3868/tcp" + - "3868/sctp" + - "5868/udp" + - "5868/tcp" + - "5868/sctp" + - "36412/sctp" + - "2123/udp" + ports: + - 36412:36412 + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.9 + pcrf: + image: openverso/open5gs:2.4.9 + entrypoint: /entrypoint_open5gs.sh + command: open5gs-pcrfd + container_name: pcrf + environment: + - DB_URI=mongodb://mongo/open5gs + depends_on: + - mongo + volumes: + - ./config/open5gs/entrypoint_open5gs.sh:/entrypoint_open5gs.sh + - ./config/open5gs/pcrf.conf:/opt/open5gs/etc/freeDiameter/pcrf.conf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3868/udp" + - "3868/tcp" + - "3868/sctp" + - "5868/udp" + - "5868/tcp" + - "5868/sctp" + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.4 + dns: + image: internetsystemsconsortium/bind9:9.18 + container_name: dns + volumes: + - ./config/bind9/e164.arpa:/etc/bind/e164.arpa + - ./config/bind9/epc_zone:/etc/bind/epc_zone + - ./config/bind9/ims_zone:/etc/bind/ims_zone + - ./config/bind9/named.conf:/etc/bind/named.conf + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "53/udp" + - "53/tcp" + ports: + - "127.0.0.1:953:953/tcp" + restart: always + networks: + default: + ipv4_address: 172.22.0.15 + rtpengine: + image: openverso/rtpengine + container_name: rtpengine + privileged: true + environment: + GW_HOSTNAME: upf + APN_IMS_SUBNET: 192.168.101.0/24 + RTPENGINE_HOSTNAME: rtpengine + volumes: + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + cap_add: + - NET_ADMIN + restart: on-failure + expose: + - "2223/udp" + - "49000-50000/udp" + networks: + default: + ipv4_address: 172.22.0.16 + mysql: + image: mariadb:10.9.3 + container_name: mysql + environment: + MARIADB_ROOT_PASSWORD: ims + volumes: + - dbdata:/var/lib/mysql + - ./config/mariadb/custom-config.cnf:/etc/mysql/conf.d/custom-config.cnf + - ./config/mariadb/my.cnf:/root/.my.cnf + - ./config/mariadb/entrypoint.sh:/docker-entrypoint-initdb.d/entrypoint.sh + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + expose: + - "3306/tcp" + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.17 + fhoss: + image: openverso/fhoss + container_name: fhoss + environment: + IMS_DOMAIN: ims.mnc001.mcc001.3gppnetwork.org + EPC_DOMAIN: openverso + volumes: + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + depends_on: + - dns + - mysql + expose: + - "3868/udp" + - "3868/tcp" + ports: + - "8080:8080/tcp" + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.18 + icscf: + image: openverso/kamailio-ims + container_name: icscf + volumes: + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - COMPONENT_NAME=icscf-1 + - IMS_DOMAIN=ims.mnc001.mcc001.3gppnetwork.org + - EPC_DOMAIN=openverso + depends_on: + - dns + - mysql + - fhoss + expose: + - "3869/udp" + - "3869/tcp" + - "4060/udp" + - "4060/tcp" + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.19 + scscf: + image: openverso/kamailio-ims + container_name: scscf + volumes: + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - COMPONENT_NAME=scscf-1 + - IMS_DOMAIN=ims.mnc001.mcc001.3gppnetwork.org + - EPC_DOMAIN=openverso + depends_on: + - dns + - mysql + - fhoss + expose: + - "3870/udp" + - "3870/tcp" + - "6060/udp" + - "6060/tcp" + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.20 + pcscf: + image: openverso/kamailio-ims + container_name: pcscf + privileged: true + cap_add: + - NET_ADMIN + volumes: + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + environment: + - COMPONENT_NAME=pcscf-1 + - IMS_DOMAIN=ims.mnc001.mcc001.3gppnetwork.org + - EPC_DOMAIN=openverso + depends_on: + - dns + - mysql + - rtpengine + - icscf + - scscf + expose: + - "3871/udp" + - "3871/tcp" + - "5060/tcp" + - "5060/udp" + - "5100-5120/tcp" + - "5100-5120/udp" + - "6100-6120/tcp" + - "6100-6120/udp" + restart: on-failure + networks: + default: + ipv4_address: 172.22.0.21 +networks: + default: + ipam: + config: + - subnet: 172.22.0.0/24 +volumes: + mongodbdata: {} + dbdata: {} diff --git a/docs/ims-open5gs-srsran/srsenb.yaml b/docs/ims-open5gs-srsran/srsenb.yaml new file mode 100644 index 0000000..4c50d71 --- /dev/null +++ b/docs/ims-open5gs-srsran/srsenb.yaml @@ -0,0 +1,33 @@ +version: '3' +services: + enodeb: + image: openverso/srsran:21_10 + container_name: srsenb + stdin_open: true + tty: true + command: + - enb + privileged: true + volumes: + - ./config/srsran/:/etc/srsran/ + - /dev/bus/usb:/dev/bus/usb + - ./uhd_images:/usr/share/uhd/images + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + cap_add: + - all + expose: + - "36412/sctp" + - "2152/udp" + environment: + UHD_IMAGES_DIR: /usr/share/uhd/images + MME_HOSTNAME: mme + ENB_HOSTNAME: enodeb + MCC: "001" + MNC: "01" + networks: + default: + ipv4_address: 172.22.0.22 +networks: + default: + name: ims-open5gs-srsran_default diff --git a/docs/ims-open5gs-srsran/uhd_image_downloader.py b/docs/ims-open5gs-srsran/uhd_image_downloader.py new file mode 100644 index 0000000..7323b8e --- /dev/null +++ b/docs/ims-open5gs-srsran/uhd_image_downloader.py @@ -0,0 +1,639 @@ +#!/usr/local/bin/python3 +# +# Copyright 2018 Ettus Research, a National Instruments Company +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +""" +Download image files required for USRPs +""" +from __future__ import print_function +import argparse +import hashlib +import json +import math +import os +import re +import shutil +import sys +import tempfile +import zipfile +import platform +# For all the non-core-library imports, we will be extra paranoid and be very +# nice with error messages so that everyone understands what's up. +try: + from urllib.parse import urljoin # Python 3 +except ImportError: + from urlparse import urljoin # Python 2 +try: + from builtins import input +except ImportError: + input = raw_input +try: + from six import iteritems +except ImportError: + sys.stdout.write( + "[ERROR] Missing module 'six'! Please install it, e.g., by " + "running 'pip install six' or any other tool that can install " + "Python modules.\n") + if platform.system() == 'Windows': + input('Hit Enter to continue.') + exit(0) +try: + import requests +except ImportError: + sys.stdout.write( + "[ERROR] Missing module 'requests'! Please install it, e.g., by " + "running 'pip install requests' or any other tool that can install " + "Python modules.\n") + if platform.system() == 'Windows': + input('Hit Enter to continue.') + exit(0) + + + +_DEFAULT_TARGET_REGEX = "(fpga|fw|windrv)_default" +_BASE_DIR_STRUCTURE_PARTS = ["share", "uhd", "images"] +_DEFAULT_INSTALL_PATH = os.path.join("/usr", *_BASE_DIR_STRUCTURE_PARTS) +_DEFAULT_BASE_URL = "http://files.ettus.com/binaries/cache/" +_INVENTORY_FILENAME = "inventory.json" +_CONTACT = "support@ettus.com" +_DEFAULT_BUFFER_SIZE = 8192 +_DEFAULT_DOWNLOAD_LIMIT = 100 * 1024 * 1024 # Bytes +_ARCHIVE_DEFAULT_TYPE = "zip" +_UHD_VERSION = "3.15.0.0-2build5" +# Note: _MANIFEST_CONTENTS are placed at the bottom of this file for aesthetic reasons +_LOG_LEVELS = {"TRACE": 1, + "DEBUG": 2, + "INFO": 3, + "WARN": 4, + "ERROR": 5} +_LOG_LEVEL = _LOG_LEVELS["INFO"] +_YES = False +_PROXIES = {} + + +def log(level, message): + """Logging function""" + message_log_level = _LOG_LEVELS.get(level, 0) + if message_log_level >= _LOG_LEVEL: + sys.stderr.write( + "[{level}] {message}\n".format(level=level, message=message)) + + +def parse_args(): + """ + Setup argument parser and parse. Also does some sanity checks and sets some + global variables we want to use. + """ + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('-t', '--types', action='append', + help="RegEx to select image sets from the manifest file.") + parser.add_argument('-i', '--install-location', + default=None, + help="Set custom install location for images") + parser.add_argument('-m', '--manifest-location', type=str, default="", + help="Set custom location for the manifest file") + parser.add_argument('-I', '--inventory-location', type=str, default="", + help="Set custom location for the inventory file") + parser.add_argument('-l', '--list-targets', action="store_true", default=False, + help="Print targets in the manifest file to stdout, and exit.\n" + "To get relative paths only, specify an empty base URL (-b '').") + parser.add_argument('--url-only', action="store_true", default=False, + help="With -l, only print the URLs, nothing else.") + parser.add_argument("--buffer-size", type=int, default=_DEFAULT_BUFFER_SIZE, + help="Set download buffer size") + parser.add_argument("--download-limit", type=int, default=_DEFAULT_DOWNLOAD_LIMIT, + help="Set threshold for download limits. Any download " + "larger than this will require approval, either " + "interactively, or by providing --yes.") + parser.add_argument("--http-proxy", type=str, + help="Specify HTTP proxy in the format " + "http://user:pass@1.2.3.4:port\n" + "If this this option is not given, the environment " + "variable HTTP_PROXY can also be used to specify a proxy.") + parser.add_argument("-b", "--base-url", type=str, default=_DEFAULT_BASE_URL, + help="Set base URL for images download location") + parser.add_argument("-k", "--keep", action="store_true", default=False, + help="Keep the downloaded images archives in the image directory") + parser.add_argument("-T", "--test", action="store_true", default=False, + help="Verify the downloaded archives before extracting them") + parser.add_argument("-y", "--yes", action="store_true", default=False, + help="Answer all questions with 'yes' (for scripting purposes).") + parser.add_argument("-n", "--dry-run", action="store_true", default=False, + help="Print selected target without actually downloading them.") + parser.add_argument("--refetch", action="store_true", default=False, + help="Ignore the inventory file and download all images.") + parser.add_argument('-V', '--version', action='version', version=_UHD_VERSION) + parser.add_argument('-q', '--quiet', action='count', default=0, + help="Decrease verbosity level") + parser.add_argument('-v', '--verbose', action='count', default=0, + help="Increase verbosity level") + # Some sanitation that's easier to handle outside of the argparse framework: + args = parser.parse_args() + if not args.base_url.endswith('/') and args.base_url != "": + args.base_url += '/' + if args.yes: + global _YES + _YES = True + if args.http_proxy: + global _PROXIES + _PROXIES['http'] = args.http_proxy + # Set the verbosity + global _LOG_LEVEL + log("TRACE", "Default log level: {}".format(_LOG_LEVEL)) + _LOG_LEVEL = _LOG_LEVEL - args.verbose + args.quiet + return args + + +def get_images_dir(args): + """ + Figure out where to store the images. + """ + if args.install_location: + return args.install_location + if os.environ.get("UHD_IMAGES_DIR"): + log("DEBUG", + "UHD_IMAGES_DIR environment variable is set, using to set " + "install location.") + return os.environ.get("UHD_IMAGES_DIR") + return _DEFAULT_INSTALL_PATH + + +def ask_permission(question, default_no=True): + """ + Ask the question, and have the user type y or n on the keyboard. If the + global variable _YES is true, this always returns True without asking the + question. Otherwise, return True if the answer is 'yes', 'y', or something + similar. + """ + if _YES: + log("DEBUG", "Assuming the answer is 'yes' for this question: " + + question) + return True + postfix = "[y/N]" if default_no else "[Y/n]" + answer = input(question + " " + postfix) + if answer and answer[0].lower() == 'y': + return True + return False + + +class TemporaryDirectory: + """Class to create a temporary directory""" + def __enter__(self): + try: + self.name = tempfile.mkdtemp() + return self.name + except Exception as ex: + log("ERROR", "Failed to create a temporary directory (%s)" % ex) + raise ex + + # Can return 'True' to suppress incoming exception + def __exit__(self, exc_type, exc_value, traceback): + try: + shutil.rmtree(self.name) + log("TRACE", "Temp directory deleted.") + except Exception as ex: + log("ERROR", "Could not delete temporary directory: %s (%s)" % (self.name, ex)) + return exc_type is None + + +def get_manifest_raw(args): + """ + Return the raw content of the manifest (i.e. the text file). It + needs to be parsed to be of any practical use. + """ + # If we're given a path to a manifest file, use it + if os.path.exists(args.manifest_location): + manifest_fn = args.manifest_location + log("INFO", "Using manifest file at location: {}".format(manifest_fn)) + with open(manifest_fn, 'r') as manifest_file: + manifest_raw = manifest_file.read() + # Otherwise, use the CMake Magic manifest + else: + manifest_raw = _MANIFEST_CONTENTS + log("TRACE", "Raw manifest contents: {}".format(manifest_raw)) + return manifest_raw + + +def parse_manifest(manifest_contents): + """Parse the manifest file, returns a dictionary of potential targets""" + manifest = {} + for line in manifest_contents.split('\n'): + line_unpacked = line.split() + try: + # Check that the line isn't empty or a comment + if not line_unpacked or line.strip().startswith('#'): + continue + + target, repo_hash, url, sha256_hash = line_unpacked + manifest[target] = {"repo_hash": repo_hash, + "url": url, + "sha256_hash": sha256_hash, + } + except ValueError: + log("WARN", "Warning: Invalid line in manifest file:\n" + " {}".format(line)) + continue + return manifest + + +def parse_inventory(inventory_fn): + """Parse the inventory file, returns a dictionary of installed files""" + try: + if not os.path.exists(inventory_fn): + log("INFO", "No inventory file found at {}. Creating an empty one.".format(inventory_fn)) + return {} + with open(inventory_fn, 'r') as inventory_file: + # TODO: verify the contents?? + return json.load(inventory_file) + except Exception as ex: + log("WARN", "Error parsing the inventory file. Assuming an empty inventory: {}".format(ex)) + return {} + + +def write_inventory(inventory, inventory_fn): + """Writes the inventory to file""" + try: + with open(inventory_fn, 'w') as inventory_file: + json.dump(inventory, inventory_file) + return True + except Exception as ex: + log("ERROR", "Error writing the inventory file. Contents may be incomplete or corrupted.\n" + "Error message: {}".format(ex)) + return False + + +def lookup_urls(regex_l, manifest, inventory, refetch=False): + """Takes a list of RegExs to match within the manifest, returns a list of tuples with + (hash, URL) that match the targets and are not in the inventory""" + selected_targets = [] + # Store whether or not we've found a target in the manifest that matches the requested type + found_one = False + for target in manifest.keys(): + # Iterate through the possible targets in the manifest. + # If any of them match any of the RegExs supplied, add the URL to the + # return list + if all(map((lambda regex: re.findall(regex, target)), regex_l)): + found_one = True + log("TRACE", "Selected target: {}".format(target)) + target_info = manifest.get(target) + target_url = target_info.get("url") + target_hash = target_info.get("repo_hash") + target_sha256 = target_info.get("sha256_hash") + filename = os.path.basename(target_url) + # Check if the same filename and hash appear in the inventory + if not refetch and inventory.get(target, {}).get("repo_hash", "") == target_hash: + # We already have this file, we don't need to download it again + log("INFO", "Target {} is up to date.".format(target)) + else: + # We don't have that exact file, add it to the list + selected_targets.append({"target": target, + "repo_hash": target_hash, + "filename": filename, + "url": target_url, + "sha256_hash": target_sha256}) + if not found_one: + log("INFO", "No targets matching '{}'".format(regex_l)) + return selected_targets + + +def print_target_list(manifest, args): + """ + Print a list of targets. + """ + char_offset = max(len(x) for x in manifest.keys()) + if not args.url_only: + # Print a couple helpful lines, + # then print each (Target, URL) pair in the manifest + log("INFO", "Potential targets in manifest file:\n" + "{} : {}".format( + "# TARGET".ljust(char_offset), + "URL" if args.base_url else "RELATIVE_URL")) + for key, value in sorted(manifest.items()): + print("{target} : {base}{relpath}".format( + target=key.ljust(char_offset), + base=args.base_url, + relpath=value["url"])) + else: + for manifest_item in iteritems(manifest): + print(args.base_url+manifest_item[1]["url"]) + + +def download( + images_url, + filename, + buffer_size=_DEFAULT_BUFFER_SIZE, + print_progress=False, + download_limit=None + ): + """ Run the download, show progress """ + download_limit = download_limit or _DEFAULT_DOWNLOAD_LIMIT + log("TRACE", "Downloading {} to {}".format(images_url, filename)) + try: + resp = requests.get(images_url, stream=True, proxies=_PROXIES, + headers={'User-Agent': 'UHD Images Downloader'}) + except TypeError: + # requests library versions pre-4c3b9df6091b65d8c72763222bd5fdefb7231149 + # (Dec.'12) workaround + resp = requests.get(images_url, prefetch=False, proxies=_PROXIES, + headers={'User-Agent': 'UHD Images Downloader'}) + if resp.status_code != 200: + raise RuntimeError("URL does not exist: {}".format(images_url)) + filesize = float(resp.headers['content-length']) + if filesize > download_limit: + if not ask_permission( + "The file size for this target ({:.1f} MiB) exceeds the " + "download limit ({:.1f} MiB). Continue downloading?".format( + filesize/1024**2, download_limit/1024**2)): + return 0, 0, "" + filesize_dl = 0 + base_filename = os.path.basename(filename) + if print_progress and not sys.stdout.isatty(): + print_progress = False + log("INFO", "Downloading {}, total size: {} kB".format( + base_filename, filesize/1000)) + with open(filename, "wb") as temp_file: + sha256_sum = hashlib.sha256() + for buff in resp.iter_content(chunk_size=buffer_size): + if buff: + temp_file.write(buff) + filesize_dl += len(buff) + sha256_sum.update(buff) + if print_progress: + status = r"%05d kB / %05d kB (%03d%%) %s" % ( + int(math.ceil(filesize_dl / 1000.)), int(math.ceil(filesize / 1000.)), + int(math.ceil(filesize_dl * 100.) / filesize), + base_filename) + if os.name == "nt": + status += chr(8) * (len(status) + 1) + else: + sys.stdout.write("\x1b[2K\r") # Clear previous line + sys.stdout.write(status) + sys.stdout.flush() + if print_progress: + print('') + return filesize, filesize_dl, sha256_sum.hexdigest() + + +def delete_from_inv(target_info, inventory, images_dir): + """ + Uses the inventory to delete the contents of the archive file specified by in `target_info` + """ + target = inventory.get(target_info.get("target"), {}) + target_name = target.get("target") + log("TRACE", "Removing contents of {} from inventory ({})".format( + target, target.get("contents", []))) + dirs_to_delete = [] + # Delete all of the files + for image_fn in target.get("contents", []): + image_path = os.path.join(images_dir, image_fn) + if os.path.isfile(image_path): + os.remove(image_path) + log("TRACE", "Deleted {} from inventory".format(image_path)) + elif os.path.isdir(image_path): + dirs_to_delete.append(image_fn) + else: # File doesn't exist + log("WARN", "File {} in inventory does not exist".format(image_path)) + # Then delete all of the (empty) directories + for dir_path in dirs_to_delete: + try: + if os.path.isdir(dir_path): + os.removedirs(dir_path) + except os.error as ex: + log("ERROR", "Failed to delete dir: {}".format(ex)) + inventory.pop(target_name, None) + return True + + +def extract(archive_path, images_dir, test_zip=False): + """ + Extract the contents of `archive_path` into `images_dir` + + Returns a list of files that were extracted. + + If test_zip is set, it will verify the zip file before extracting. + """ + log("TRACE", "Attempting to extracted files from {}".format(archive_path)) + with zipfile.ZipFile(archive_path) as images_zip: + # Check that the Zip file is valid, in which case `testzip()` returns + # None. If it's bad, that function will return a list of bad files + try: + if test_zip and images_zip.testzip(): + log("ERROR", "Could not extract the following invalid Zip file:" + " {}".format(archive_path)) + return [] + except OSError: + log("ERROR", "Could not extract the following invalid Zip file:" + " {}".format(archive_path)) + return [] + images_zip.extractall(images_dir) + archive_namelist = images_zip.namelist() + log("TRACE", "Extracted files: {}".format(archive_namelist)) + return archive_namelist + + +def update_target(target_info, temp_dir, images_dir, inventory, args): + """ + Handle the updating of a single target. + """ + target_name = target_info.get("target") + target_sha256 = target_info.get("sha256_hash") + filename = target_info.get("filename") + temp_path = os.path.join(temp_dir, filename) + # Add a trailing slash to make sure that urljoin handles things properly + full_url = urljoin(args.base_url+'/', target_info.get("url")) + _, downloaded_size, downloaded_sha256 = download( + images_url=full_url, + filename=temp_path, + buffer_size=args.buffer_size, + print_progress=(_LOG_LEVEL <= _LOG_LEVELS.get("INFO", 3)) + ) + if downloaded_size == 0: + log("INFO", "Skipping target: {}".format(target_name)) + return + log("TRACE", "{} successfully downloaded ({} Bytes)" + .format(temp_path, downloaded_size)) + # If the SHA256 in the manifest has the value '0', this is a special case + # and we just skip the verification step + if target_sha256 == '0': + log("DEBUG", "Skipping SHA256 check for {}.".format(full_url)) + # If the check fails, print an error and don't unzip the file + elif downloaded_sha256 != target_sha256: + log("ERROR", "Downloaded SHA256 does not match manifest for {}!" + .format(full_url)) + return + # Note: this skips the --keep option, so we'll never keep image packages + # that fail the SHA256 checksum + ## Now copy the contents to the final destination (the images directory) + delete_from_inv(target_info, inventory, images_dir) + if os.path.splitext(temp_path)[1].lower() == '.zip': + archive_namelist = extract( + temp_path, + images_dir, + args.test) + if args.keep: + # If the user wants to keep the downloaded archive, + # save it to the images directory and add it to the inventory + shutil.copy(temp_path, images_dir) + archive_namelist.append(filename) + else: + archive_namelist = [] + shutil.copy(temp_path, images_dir) + ## Update inventory + inventory[target_name] = {"repo_hash": target_info.get("repo_hash"), + "contents": archive_namelist, + "filename": filename} + + +def main(): + """ + Main function; does whatever the user requested (download or list files). + + Returns True on successful execution. + """ + args = parse_args() + images_dir = get_images_dir(args) + log("INFO", "Images destination: {}".format(os.path.abspath(images_dir))) + try: + manifest = parse_manifest(get_manifest_raw(args)) + if args.list_targets: + print_target_list( + manifest, + args + ) + return True + log("TRACE", "Manifest:\n{}".format( + "\n".join("{}".format(item) for item in manifest.items()) + )) + + # Read the inventory into a dictionary we can perform lookups on + if os.path.isfile(args.inventory_location): + inventory_fn = args.inventory_location + else: + inventory_fn = os.path.join(images_dir, _INVENTORY_FILENAME) + inventory = parse_inventory(inventory_fn=inventory_fn) + log("TRACE", "Inventory: {}\n{}".format( + os.path.abspath(inventory_fn), + "\n".join("{}".format(item) for item in inventory.items()) + )) + + # Determine the URLs to download based on the input regular expressions + if not args.types: + types_regex_l = [_DEFAULT_TARGET_REGEX] + else: + types_regex_l = args.types + + log("TRACE", "RegExs for target selection: {}".format(types_regex_l)) + targets_info = lookup_urls(types_regex_l, manifest, inventory, args.refetch) + # Exit early if we don't have anything to download + if targets_info: + target_urls = [info.get("url") for info in targets_info] + log("DEBUG", "URLs to download:\n{}".format( + "\n".join("{}".format(item) for item in target_urls) + )) + else: + return True + + ## Now download all the images archives into a temp directory + if args.dry_run: + for target_info in targets_info: + log("INFO", "[Dry Run] Fetch target: {}".format( + target_info.get("filename"))) + return True + with TemporaryDirectory() as temp_dir: + for target_info in targets_info: + update_target( + target_info, + temp_dir, + images_dir, + inventory, + args + ) + ## Update inventory with all the new content + write_inventory(inventory, inventory_fn) + + except Exception as ex: + log("ERROR", "Downloader raised an unhandled exception: {ex}\n" + "You can run this again with the '--verbose' flag to see more information\n" + "If the problem persists, please email the output to: {contact}" + .format(contact=_CONTACT, ex=ex)) + # Again, we wait on Windows systems because if this is executed in a + # window, and immediately fails, the user doesn't have a way to see the + # error message, and if they're not very savvy, they won't know how to + # execute this in a shell. + if not _YES and platform.system() == 'Windows': + input('Hit Enter to continue.') + return False + log("INFO", "Images download complete.") + return True + +# Placing this near the end of the file so we don't clutter the top +_MANIFEST_CONTENTS = """# UHD Image Manifest File +# Target hash url SHA256 +# X300-Series +x3xx_x310_fpga_default fpga-fde2a94eb x3xx/fpga-fde2a94eb/x3xx_x310_fpga_default-gfde2a94e.zip ac5bcf4b85773508bdc3b5e882bfa14025a7867b4c1858f5751439919ee6d270 +x3xx_x300_fpga_default fpga-fde2a94eb x3xx/fpga-fde2a94eb/x3xx_x300_fpga_default-gfde2a94e.zip 2bdfb7851f6b9aebadfe3aa227d93532bd005fcae4b4d88ae74522f903bd4081 +# Example daughterboard targets (none currently exist) +#x3xx_twinrx_cpld_default example_target +#dboard_ubx_cpld_default example_target + +# E-Series +e3xx_e310_sg1_fpga_default fpga-fde2a94eb e3xx/fpga-fde2a94eb/e3xx_e310_sg1_fpga_default-gfde2a94e.zip ac5f6db65780e944c565977e0bd5085c76d0bcdf246579f13d5da69211590980 +e3xx_e310_sg3_fpga_default fpga-fde2a94eb e3xx/fpga-fde2a94eb/e3xx_e310_sg3_fpga_default-gfde2a94e.zip 84ddae28d98d02cdeb88b560dc6c1f7280f8d9adcc719bec9774deb7ed6dbb3c +e3xx_e320_fpga_default fpga-fde2a94eb e3xx/fpga-fde2a94eb/e3xx_e320_fpga_default-gfde2a94e.zip 95064badda9b93281b01e642faff9577d054883869896899e28293a243d8862c + +# E310 Filesystems +e3xx_e310_sdk_default meta-ettus-v3.15.0.0 e3xx/meta-ettus-v3.15.0.0/e3xx_e310_sdk_default-v3.15.0.0.zip 0 +e3xx_e310_sg1_mender_default meta-ettus-v3.15.0.0 e3xx/meta-ettus-v3.15.0.0/e3xx_e310_sg1_mender_default-v3.15.0.0.zip 0 +e3xx_e310_sg1_sdimg_default meta-ettus-v3.15.0.0 e3xx/meta-ettus-v3.15.0.0/e3xx_e310_sg1_sdimg_default-v3.15.0.0.zip 0 +e3xx_e310_sg3_mender_default meta-ettus-v3.15.0.0 e3xx/meta-ettus-v3.15.0.0/e3xx_e310_sg3_mender_default-v3.15.0.0.zip 0 +e3xx_e310_sg3_sdimg_default meta-ettus-v3.15.0.0 e3xx/meta-ettus-v3.15.0.0/e3xx_e310_sg3_sdimg_default-v3.15.0.0.zip 0 + +# E320 Filesystems, etc +e3xx_e320_sdk_default meta-ettus-v3.15.0.0 e3xx/meta-ettus-v3.15.0.0/e3xx_e320_sdk_default-v3.15.0.0.zip 0 +e3xx_e320_mender_default meta-ettus-v3.15.0.0 e3xx/meta-ettus-v3.15.0.0/e3xx_e320_mender_default-v3.15.0.0.zip 0 +e3xx_e320_sdimg_default meta-ettus-v3.15.0.0 e3xx/meta-ettus-v3.15.0.0/e3xx_e320_sdimg_default-v3.15.0.0.zip 0 + +# N300-Series +n3xx_n310_fpga_default fpga-fde2a94eb n3xx/fpga-fde2a94eb/n3xx_n310_fpga_default-gfde2a94e.zip 4a45e2d4ec41d34fc550402928248a15488ba7b58d835ef2d4f503556173764a +n3xx_n300_fpga_default fpga-fde2a94eb n3xx/fpga-fde2a94eb/n3xx_n300_fpga_default-gfde2a94e.zip 7f1b512756ae225f8caaf20fd22d2e1537ea211b2fd6c4c9ed1330065fb56645 +n3xx_n320_fpga_default fpga-fde2a94eb n3xx/fpga-fde2a94eb/n3xx_n320_fpga_default-gfde2a94e.zip 4fae9de2ede7ff446da8afb61808868c08ba32f8e3092b802c5d4d7643c7175f +n3xx_n310_cpld_default fpga-6bea23d n3xx/fpga-6bea23d/n3xx_n310_cpld_default-g6bea23d.zip ef128dcd265ee8615b673021d4ee84c39357012ffe8b28c8ad7f893f9dcb94cb +n3xx_n320_cpld_default fpga-4bc2c6f n3xx/fpga-4bc2c6f/n3xx_n320_cpld_default-g4bc2c6f.zip 6680a9363efc5fa8b5a68beb3dff44f2e314b94e716e3a1751aba0fed1f384da +# N3XX Mykonos firmware +#n3xx_n310_fw_default fpga-6bea23d n3xx/fpga-6bea23d/n3xx_n310_fw_default-g6bea23d.zip 0 +# N300-Series Filesystems, etc +n3xx_common_sdk_default meta-ettus-v3.15.0.0 n3xx/meta-ettus-v3.15.0.0/n3xx_common_sdk_default-v3.15.0.0.zip 0 +n3xx_common_mender_default meta-ettus-v3.15.0.0 n3xx/meta-ettus-v3.15.0.0/n3xx_common_mender_default-v3.15.0.0.zip 0 +n3xx_common_sdimg_default meta-ettus-v3.15.0.0 n3xx/meta-ettus-v3.15.0.0/n3xx_common_sdimg_default-v3.15.0.0.zip 0 + +# B200-Series +b2xx_b200_fpga_default fpga-fde2a94eb b2xx/fpga-fde2a94eb/b2xx_b200_fpga_default-gfde2a94e.zip 44885476f1bce75657e4dd78ba03830e662a59b6bb612a90e9f8041306deb68e +b2xx_b200mini_fpga_default fpga-fde2a94eb b2xx/fpga-fde2a94eb/b2xx_b200mini_fpga_default-gfde2a94e.zip 4318249e394be686e99c58effa162209aa496a039c68ef816f0b2f9247485c12 +b2xx_b210_fpga_default fpga-fde2a94eb b2xx/fpga-fde2a94eb/b2xx_b210_fpga_default-gfde2a94e.zip 936864ec5e9627f786c3cd3687c761a24a0ff68a99e224fcc2b24cb4d4197dd2 +b2xx_b205mini_fpga_default fpga-fde2a94eb b2xx/fpga-fde2a94eb/b2xx_b205mini_fpga_default-gfde2a94e.zip cd3dad8c70925c0c79e728716c0ebb36f2145e1cf929409fa77c953637effd70 +b2xx_common_fw_default uhd-2bdad498 b2xx/uhd-2bdad498/b2xx_common_fw_default-g2bdad498.zip a6a867466448f2f75d9d5d290c57ceb8e1d3219391c9f275824fbeb3e7931732 + +# USRP2 Devices +usrp2_usrp2_fw_default fpga-6bea23d usrp2/fpga-6bea23d/usrp2_usrp2_fw_default-g6bea23d.zip d523a18318cb6a7637be40484bf03a6f54766410fee2c1a1f72e8971ea9a9cb6 +usrp2_usrp2_fpga_default fpga-6bea23d usrp2/fpga-6bea23d/usrp2_usrp2_fpga_default-g6bea23d.zip 505c70aedc8cdfbbfe654bcdbe1ce604c376e733a44cdd1351571f61a7f1cb49 +usrp2_n200_fpga_default fpga-6bea23d usrp2/fpga-6bea23d/usrp2_n200_fpga_default-g6bea23d.zip 833a0098d66c0c502b9c3975d651a79e125133c507f9f4b2c472f9eb96fdaef8 +usrp2_n200_fw_default fpga-6bea23d usrp2/fpga-6bea23d/usrp2_n200_fw_default-g6bea23d.zip 3eee2a6195caafe814912167fccf2dfc369f706446f8ecee36e97d2c0830116f +usrp2_n210_fpga_default fpga-6bea23d usrp2/fpga-6bea23d/usrp2_n210_fpga_default-g6bea23d.zip 5ce68ac539ee6eeb7d04fb3127c1fabcaff442a8edfaaa2f3746590f9df909bd +usrp2_n210_fw_default fpga-6bea23d usrp2/fpga-6bea23d/usrp2_n210_fw_default-g6bea23d.zip 3646fcd3fc974d18c621cb10dfe97c4dad6d282036dc63b7379995dfad95fb98 +n230_n230_fpga_default fpga-fde2a94eb n230/fpga-fde2a94eb/n230_n230_fpga_default-gfde2a94e.zip 5436932bc8a459c6e350885b67f907f7c864edd71c0089f6692636428b3c20a9 + +# USRP1 Devices +usrp1_usrp1_fpga_default fpga-6bea23d usrp1/fpga-6bea23d/usrp1_usrp1_fpga_default-g6bea23d.zip 03bf72868c900dd0853bf48e2ede91058d579829b0e70c021e51b0e282d1d5be +usrp1_b100_fpga_default fpga-6bea23d usrp1/fpga-6bea23d/usrp1_b100_fpga_default-g6bea23d.zip 7f2306f21e17aa3fae3f966d08c6297d6cf42041974f846ca89f0d633ece8769 +usrp1_b100_fw_default fpga-6bea23d usrp1/fpga-6bea23d/usrp1_b100_fw_default-g6bea23d.zip 867f17fac085535dbcb01c226ce87acf49806de6ed0ae9b214d7c8da86e2a71d + +# Octoclock +octoclock_octoclock_fw_default uhd-14000041 octoclock/uhd-14000041/octoclock_octoclock_fw_default-g14000041.zip 8da7f1af8cecb7f6259a237a18c39058ba69a11567fa373cffc9704031a1d053 + +# Legacy USB Windows drivers +usb_common_windrv_default uhd-14000041 usb/uhd-14000041/usb_common_windrv_default-g14000041.zip 835e94b2bdf2312fd3881a1b78e2ec236c1f42b7a5bd3927f85f73cf5e3a5231 +""" +if __name__ == "__main__": + sys.exit(not main()) diff --git a/images/fhoss/Dockerfile b/images/fhoss/Dockerfile new file mode 100644 index 0000000..ccc7199 --- /dev/null +++ b/images/fhoss/Dockerfile @@ -0,0 +1,80 @@ +# THIRD PARTY SOFTWARE NOTICES AND INFORMATION +# Do Not Translate or Localize +# +# This repository includes Oracle Java 7 JDK downloaded from Oracle website, which is distributed +# under Oracle Binary Code License Agreement for Java SE. By using this repository you agree to +# have reviewed and accepted the Oracle Binary Code License Agreement for Java SE and hold +# no liability. +# +# ========================================= + +# 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 git vim wget subversion mysql-server dnsutils ed + +# Install Oracle Java 7 SE JDK +RUN mkdir -p /usr/lib/jvm/ && \ + cd / && wget https://files-cdn.liferay.com/mirrors/download.oracle.com/otn-pub/java/jdk/7u80-b15/jdk-7u80-linux-x64.tar.gz && \ + tar -zxf /jdk-7u80-linux-x64.tar.gz -C /usr/lib/jvm/ && \ + update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk1.7.0_80/bin/java 100 && \ + update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/jdk1.7.0_80/bin/javac 100 + +# Install Ant +RUN cd / && wget http://archive.apache.org/dist/ant/binaries/apache-ant-1.9.14-bin.tar.gz && \ + tar xvfvz apache-ant-1.9.14-bin.tar.gz && \ + mv apache-ant-1.9.14 /usr/local/ && \ + ln -s /usr/local/apache-ant-1.9.14/bin/ant /usr/bin/ant + +RUN mkdir -p /opt/OpenIMSCore && \ + cd /opt/OpenIMSCore && \ + git clone https://github.com/herlesupreeth/FHoSS + +ENV JAVA_HOME="/usr/lib/jvm/jdk1.7.0_80" +ENV CLASSPATH="/usr/lib/jvm/jdk1.7.0_80/jre/lib/" +ENV ANT_HOME="/usr/local/apache-ant-1.9.14" +ENV LC_ALL=C.UTF-8 +ENV LANG=C.UTF-8 +ENV IMS_DOMAIN=ims.mnc001.mcc001.3gppnetwork.org \ + EPC_DOMAIN=openverso \ + MYSQL_HOSTNAME=mysql \ + DNS_HOSTNAME=dns \ + FHOSS_HOSTNAME=fhoss + +RUN cd /opt/OpenIMSCore/FHoSS && \ + ant compile deploy | tee ant_compile_deploy.txt + +COPY resources/ /mnt/fhoss/ + +RUN chmod +x /mnt/fhoss/fhoss_init.sh + +CMD /mnt/fhoss/fhoss_init.sh diff --git a/images/fhoss/image_info.sh b/images/fhoss/image_info.sh new file mode 100644 index 0000000..266a7b8 --- /dev/null +++ b/images/fhoss/image_info.sh @@ -0,0 +1,3 @@ +IMAGE_TAG=develop +#comma separated list of platforms. If empty, image will not be multiarch. +PLATFORMS=linux/amd64 \ No newline at end of file diff --git a/images/fhoss/resources/DiameterPeerHSS.xml b/images/fhoss/resources/DiameterPeerHSS.xml new file mode 100644 index 0000000..d76b10e --- /dev/null +++ b/images/fhoss/resources/DiameterPeerHSS.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + diff --git a/images/fhoss/resources/configurator.sh b/images/fhoss/resources/configurator.sh new file mode 100755 index 0000000..8dca84a --- /dev/null +++ b/images/fhoss/resources/configurator.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Initialization & global vars +# if you execute this script for the second time +# you should change these variables to the latest +# domain name and ip address +DDOMAIN="open-ims\.test" +DSDOMAIN="open-ims\\\.test" +DEFAULTIP="127\.0\.0\.1" +CONFFILES=`ls *.cfg *.xml *.sql *.properties 2>/dev/null` + +# Interaction +domainname=$1 +ip_address=$2 + +# input domain is to be slashed for cfg regexes +slasheddomain=`echo $domainname | sed 's/\./\\\\\\\\\./g'` + +printf "changing: " +for i in $CONFFILES +do +sed -i -e "s/$DDOMAIN/$domainname/g" $i +sed -i -e "s/$DSDOMAIN/$slasheddomain/g" $i +sed -i -e "s/$DEFAULTIP/$ip_address/g" $i + +printf "$i " +done +echo diff --git a/images/fhoss/resources/fhoss_init.sh b/images/fhoss/resources/fhoss_init.sh new file mode 100755 index 0000000..a44c760 --- /dev/null +++ b/images/fhoss/resources/fhoss_init.sh @@ -0,0 +1,122 @@ +#!/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. + +# Temporary patch to solve the case of docker internal dns not resolving "not running" container names. +# Just wait 10 seconds to be "running" and resolvable +sleep 10 + +MYSQL_IP=${MYSQL_IP:-"$(host -4 $MYSQL_HOSTNAME |awk '/has.*address/{print $NF; exit}')"} +export MYSQL_IP +echo "MYSQL_IP: $MYSQL_IP" + +FHOSS_IP=${FHOSS_IP:-"$(host -4 $FHOSS_HOSTNAME |awk '/has.*address/{print $NF; exit}')"} +export FHOSS_IP +echo "FHOSS_IP: $FHOSS_IP" + +DNS_IP=${DNS_IP:-"$(host -4 $DNS_HOSTNAME |awk '/has.*address/{print $NF; exit}')"} +export DNS_IP +echo "DNS_IP: $DNS_IP" + + +if [ -z "$MYSQL_IP" ] \ + || [[ -z "$FHOSS_IP" ]] \ + || [[ -z "$DNS_IP" ]]; then +echo "Unable to resolve some IPs... restarting" +exit 1 +fi + +IMS_DOMAIN=$IMS_DOMAIN + +cp /mnt/fhoss/configurator.sh /opt/OpenIMSCore/FHoSS/deploy +cp /mnt/fhoss/DiameterPeerHSS.xml /opt/OpenIMSCore/FHoSS/deploy +cp /mnt/fhoss/hibernate.properties /opt/OpenIMSCore/FHoSS/deploy +cp /mnt/fhoss/configurator.sh /opt/OpenIMSCore/FHoSS/scripts +cp /mnt/fhoss/configurator.sh /opt/OpenIMSCore/FHoSS/config + +cd /opt/OpenIMSCore/FHoSS/deploy && ./configurator.sh ${IMS_DOMAIN} ${FHOSS_IP} +sed -i 's|open-ims.org|'$IMS_DOMAIN'|g' /opt/OpenIMSCore/FHoSS/deploy/webapps/hss.web.console/WEB-INF/web.xml +sed -i 's|${MYSQL_IP}|'$MYSQL_IP'|g' /opt/OpenIMSCore/FHoSS/deploy/hibernate.properties +sed -i 's|${FHOSS_IP}|'$FHOSS_IP'|g' /opt/OpenIMSCore/FHoSS/deploy/DiameterPeerHSS.xml +sed -i 's|${IMS_DOMAIN}|'$IMS_DOMAIN'|g' /opt/OpenIMSCore/FHoSS/deploy/DiameterPeerHSS.xml +cd /opt/OpenIMSCore/FHoSS/scripts && ./configurator.sh ${IMS_DOMAIN} ${FHOSS_IP} +cd /opt/OpenIMSCore/FHoSS/config && ./configurator.sh ${IMS_DOMAIN} ${FHOSS_IP} +sed -i 's|open-ims.org|'$IMS_DOMAIN'|g' /opt/OpenIMSCore/FHoSS/src-web/WEB-INF/web.xml + +while ! mysqladmin ping -h ${MYSQL_IP} --silent; do + sleep 5; +done + +# Sleep until permissions are set +sleep 10; + +# Create FHoSS 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='hss_db'" 2>&1`" ]]; +then + mysql -u root -h ${MYSQL_IP} -e "create database hss_db;" + mysql -u root -h ${MYSQL_IP} hss_db < /opt/OpenIMSCore/FHoSS/scripts/hss_db.sql + FHOSS_USER_EXISTS=`mysql -u root -h ${MYSQL_IP} -s -N -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE User = 'hss' AND Host = '%')"` + if [[ "$FHOSS_USER_EXISTS" == 0 ]] + then + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'hss'@'%' IDENTIFIED VIA mysql_native_password USING PASSWORD('hss')"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'hss'@'$FHOSS_IP' IDENTIFIED VIA mysql_native_password USING PASSWORD('hss')"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON hss_db.* TO 'hss'@'%'"; + mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON hss_db.* TO 'hss'@'$FHOSS_IP'"; + mysql -u root -h ${MYSQL_IP} -e "FLUSH PRIVILEGES;" + fi + mysql -u root -h ${MYSQL_IP} hss_db < /opt/OpenIMSCore/FHoSS/scripts/userdata.sql +fi + +VIS_NET_PRESENT=`mysql -u root -h ${MYSQL_IP} hss_db -s -N -e "SELECT count(*) FROM visited_network;"` +if [[ "$VIS_NET_PRESENT" -gt 0 ]] +then + mysql -u root -h ${MYSQL_IP} hss_db -e "DELETE FROM visited_network;" + mysql -u root -h ${MYSQL_IP} hss_db -e "INSERT INTO visited_network VALUES (1, '$IMS_DOMAIN');" +fi + +PREF_SCSCF_PRESENT=`mysql -u root -h ${MYSQL_IP} hss_db -s -N -e "SELECT count(*) FROM preferred_scscf_set;"` +if [[ "$PREF_SCSCF_PRESENT" -gt 0 ]] +then + mysql -u root -h ${MYSQL_IP} hss_db -e "DELETE FROM preferred_scscf_set;" + mysql -u root -h ${MYSQL_IP} hss_db -e "INSERT INTO preferred_scscf_set VALUES (1, 1, 'scscf1', 'sip:scscf.$IMS_DOMAIN:6060', 0);" +fi + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# Configure dns service as main nameserver +sleep 5 +ed /etc/resolv.conf << END +1i +nameserver ${DNS_IP} +. +w +q +END + +cp /mnt/fhoss/hss.sh / +cd / && ./hss.sh diff --git a/images/fhoss/resources/hibernate.properties b/images/fhoss/resources/hibernate.properties new file mode 100644 index 0000000..88dee9b --- /dev/null +++ b/images/fhoss/resources/hibernate.properties @@ -0,0 +1,21 @@ +## MySQL + +# hibernate configuration +hibernate.dialect=org.hibernate.dialect.MySQLDialect +#hibernate.connection.driver_class=org.gjt.mm.mysql.Driver +hibernate.connection.driver_class=com.mysql.jdbc.Driver +hibernate.connection.url=jdbc:mysql://${MYSQL_IP}:3306/hss_db +hibernate.connection.username=hss +hibernate.connection.password=hss +hibernate.connection.isolation=1 +hibernate.connection.characterEncoding=utf8 +hibernate.connection.useUnicode=true +hibernate.connection.CharSet=utf8 + +# C3P0 configuration +hibernate.c3p0.acquire_increment=1 +hibernate.c3p0.min_size=1 +hibernate.c3p0.max_size=30 +hibernate.c3p0.timeout=3600 +hibernate.c3p0.max_statements=0 +hibernate.c3p0.idle_test_period=1200 diff --git a/images/fhoss/resources/hss.sh b/images/fhoss/resources/hss.sh new file mode 100755 index 0000000..fca4dcd --- /dev/null +++ b/images/fhoss/resources/hss.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# -------------------------------------------------------------- +# Include JAR Files +# -------------------------------------------------------------- + +cd /opt/OpenIMSCore/FHoSS/deploy +JAVA_HOME="/usr/lib/jvm/jdk1.7.0_80" +CLASSPATH="/usr/lib/jvm/jdk1.7.0_80/jre/lib/" +echo "Building Classpath" +CLASSPATH=$CLASSPATH:log4j.properties:. +for i in lib/*.jar; do CLASSPATH="$i":"$CLASSPATH"; done +echo "Classpath is $CLASSPATH." + +# -------------------------------------------------------------- +# Start-up +# -------------------------------------------------------------- + +$JAVA_HOME/bin/java -cp $CLASSPATH de.fhg.fokus.hss.main.HSSContainer $1 $2 $3 $4 $5 $6 $7 $8 $9 diff --git a/images/kamailio-ims/Dockerfile b/images/kamailio-ims/Dockerfile new file mode 100644 index 0000000..6395b51 --- /dev/null +++ b/images/kamailio-ims/Dockerfile @@ -0,0 +1,72 @@ +# 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 libpcre3-dev bash-completion g++ autoconf libmnl-dev \ + libsctp-dev libradcli-dev libradcli4 libjson-c-dev pkg-config iproute2 net-tools \ + iputils-ping dnsutils ed + +# Fetch Kamailio code (branch 5.3) +RUN mkdir -p /usr/local/src/ && cd /usr/local/src/ && \ + git clone https://github.com/herlesupreeth/kamailio && \ + cd kamailio && git checkout 5.3 + +ENV IMS_DOMAIN=ims.mnc001.mcc001.3gppnetwork.org \ + EPC_DOMAIN=openverso \ + MYSQL_HOSTNAME=mysql \ + PCSCF_HOSTNAME=pcscf \ + RTPENGINE_HOSTNAME=rtpengine \ + UPF_HOSTNAME=upf \ + ICSCF_HOSTNAME=icscf \ + SCSCF_HOSTNAME=scscf \ + DNS_HOSTNAME=dns + +# 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 icscf/ /mnt/icscf/ +RUN chmod +x /mnt/icscf/icscf_init.sh + +COPY pcscf/ /mnt/pcscf/ +RUN chmod +x /mnt/pcscf/pcscf_init.sh + +COPY scscf/ /mnt/scscf/ +RUN chmod +x /mnt/scscf/scscf_init.sh + +COPY kamailio_init.sh / +CMD /kamailio_init.sh diff --git a/images/kamailio-ims/icscf/icscf.cfg b/images/kamailio-ims/icscf/icscf.cfg new file mode 100644 index 0000000..de68194 --- /dev/null +++ b/images/kamailio-ims/icscf/icscf.cfg @@ -0,0 +1,52 @@ +# 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 "IMS_DOMAIN." + +# 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_TCP +##!define WITH_TLS +#!define WITH_XMLRPC +##!define PEERING +##!define FALLBACK_AUTH diff --git a/images/kamailio-ims/icscf/icscf.xml b/images/kamailio-ims/icscf/icscf.xml new file mode 100644 index 0000000..5fd38ef --- /dev/null +++ b/images/kamailio-ims/icscf/icscf.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + diff --git a/images/kamailio-ims/icscf/icscf_init.sh b/images/kamailio-ims/icscf/icscf_init.sh new file mode 100755 index 0000000..3ea2b7a --- /dev/null +++ b/images/kamailio-ims/icscf/icscf_init.sh @@ -0,0 +1,125 @@ +#!/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. + +# Temporary patch to solve the case of docker internal dns not resolving "not running" container names. +# Just wait 10 seconds to be "running" and resolvable +sleep 10 + +MYSQL_IP=${MYSQL_IP:-"$(host -4 $MYSQL_HOSTNAME |awk '/has.*address/{print $NF; exit}')"} +export MYSQL_IP +echo "MYSQL_IP: $MYSQL_IP" + +ICSCF_IP=${ICSCF_IP:-"$(host -4 $ICSCF_HOSTNAME |awk '/has.*address/{print $NF; exit}')"} +export ICSCF_IP +echo "ICSCF_IP: $ICSCF_IP" + +DNS_IP=${DNS_IP:-"$(host -4 $DNS_HOSTNAME |awk '/has.*address/{print $NF; exit}')"} +export DNS_IP +echo "DNS_IP: $DNS_IP" + +if [ -z "$MYSQL_IP" ] \ + || [[ -z "$ICSCF_IP" ]] \ + || [[ -z "$DNS_IP" ]]; then +echo "Unable to resolve some IPs... restarting" +exit 1 +fi + +IMS_DOMAIN=$IMS_DOMAIN + +mkdir /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 VIA mysql_native_password USING PASSWORD('heslo')"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'provisioning'@'%' IDENTIFIED VIA mysql_native_password USING PASSWORD('provi')"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'icscf'@'$ICSCF_IP' IDENTIFIED VIA mysql_native_password USING PASSWORD('heslo')"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'provisioning'@'$ICSCF_IP' IDENTIFIED VIA mysql_native_password USING PASSWORD('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 + +sed -i 's|ICSCF_IP|'$ICSCF_IP'|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|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/kamailio_icscf/icscf.xml + +# Configure dns service as main nameserver +sleep 5 +ed /etc/resolv.conf << END +1i +nameserver ${DNS_IP} +. +w +q +END +cat /etc/resolv.conf + +# Sync docker time +#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/images/kamailio-ims/icscf/kamailio_icscf.cfg b/images/kamailio-ims/icscf/kamailio_icscf.cfg new file mode 100644 index 0000000..3571128 --- /dev/null +++ b/images/kamailio-ims/icscf/kamailio_icscf.cfg @@ -0,0 +1,639 @@ +#!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 ######### +#!ifdef WITH_DEBUG +debug=5 +log_stderror=yes +sip_warning=yes +#!else +debug=2 +log_stderror=no +sip_warning=no +#!endif + +user_agent_header="User-Agent: Kamailio I-CSCF" +server_header="Server: Kamailio I-CSCF" + +/* 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=3615 +#!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", 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", "cfgtrace", 1) +#!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/images/kamailio-ims/image_info.sh b/images/kamailio-ims/image_info.sh new file mode 100644 index 0000000..51d6bbd --- /dev/null +++ b/images/kamailio-ims/image_info.sh @@ -0,0 +1,3 @@ +IMAGE_TAG=5.3-dev +#comma separated list of platforms. If empty, image will not be multiarch. +PLATFORMS=linux/amd64 \ No newline at end of file diff --git a/images/kamailio-ims/kamailio_init.sh b/images/kamailio-ims/kamailio_init.sh new file mode 100755 index 0000000..8cb62e8 --- /dev/null +++ b/images/kamailio-ims/kamailio_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. + +echo "Waiting..." +sleep 30 + +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/icscf_init.sh && \ + mkdir -p /var/run/kamailio_icscf && \ + 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/scscf_init.sh && \ + mkdir -p /var/run/kamailio_scscf && \ + 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/pcscf_init.sh && \ + mkdir -p /var/run/kamailio_pcscf && \ + kamailio -f /etc/kamailio_pcscf/kamailio_pcscf.cfg -P /kamailio_pcscf.pid -DD -E -e +else + echo "Error: Invalid component name: '$COMPONENT_NAME'" +fi diff --git a/images/kamailio-ims/modules.lst b/images/kamailio-ims/modules.lst new file mode 100644 index 0000000..7765df1 --- /dev/null +++ b/images/kamailio-ims/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 json 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 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 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= acc_json acc_radius app_java app_lua app_lua_sr app_mono app_perl app_python app_python3 app_ruby 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 http_async_client jansson janssonrpcc jsonrpcc jwt kafka kazoo lcr ldap log_systemd lost lwsc memcached misc_radius ndb_cassandra mqtt ndb_mongodb ndb_redis nsq osp peering phonenum pua_json rabbitmq regex rls rtp_media_server secsipid secsipid_proc snmpstats stirshaken systemdops topos_redis uuid websocket xhttp_pi xmpp $(skip_modules) + +modules_all= $(filter-out modules/CVS,$(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/images/kamailio-ims/pcscf/dispatcher.list b/images/kamailio-ims/pcscf/dispatcher.list new file mode 100644 index 0000000..47d4d4f --- /dev/null +++ b/images/kamailio-ims/pcscf/dispatcher.list @@ -0,0 +1 @@ +# SBC's diff --git a/images/kamailio-ims/pcscf/kamailio_pcscf.cfg b/images/kamailio-ims/pcscf/kamailio_pcscf.cfg new file mode 100644 index 0000000..5389152 --- /dev/null +++ b/images/kamailio-ims/pcscf/kamailio_pcscf.cfg @@ -0,0 +1,997 @@ +# +# 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 ######### + +#!ifdef WITH_DEBUG +debug=4 +log_stderror=yes +#!else +debug=2 +log_stderror=no +#!endif + +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 + +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=36000 +# 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" +# Transaction Module +loadmodule "tm" +loadmodule "tmx" +loadmodule "sl" +loadmodule "rr" +loadmodule "pv" +loadmodule "maxfwd" +loadmodule "textops" +loadmodule "textopsx" +# SIP-Utilities: options_reply +loadmodule "siputils" +loadmodule "sanity" +loadmodule "ctl" +loadmodule "cfg_rpc" +loadmodule "xlog" +loadmodule "auth" +loadmodule "dispatcher" +loadmodule "sctp" +loadmodule "path" +loadmodule "statistics" + +loadmodule "ims_dialog" +loadmodule "ims_usrloc_pcscf" +#!ifdef WITH_IPSEC +loadmodule "ims_ipsec_pcscf" +#!endif +loadmodule "ims_registrar_pcscf" + +#!ifdef WITH_XMLRPC +loadmodule "xmlrpc" +#!endif + +#!ifdef WITH_REGINFO +loadmodule "pua" +#!endif + +#!ifdef DB_URL +loadmodule "db_mysql" +#!ifdef DB_URL2 +loadmodule "db_cluster" +#!endif +#!endif + +#!ifdef WITH_DEBUG +loadmodule "debugger" +#!endif + +loadmodule "usrloc" +loadmodule "registrar" + +loadmodule "nathelper" + +#!ifdef WITH_ANTIFLOOD +loadmodule "pike" +#!endif + +#!ifdef WITH_TLS +loadmodule "tls" +#!endif + +#!ifdef WITH_RTPPING +loadmodule "rtpping" +#!endif + + +loadmodule "sdpops" +loadmodule "rtpengine" + +#!ifdef WITH_WEBSOCKET +loadmodule "xhttp.so" +loadmodule "websocket.so" +#!endif + +#!ifdef WITH_RX +loadmodule "cdp" +loadmodule "cdp_avp" +loadmodule "ims_qos" +#!endif + +#!ifdef CAPTURE_NODE +loadmodule "siptrace" +#!endif + +#!ifdef WITH_NATPING +loadmodule "rtimer" +loadmodule "uac" +loadmodule "sqlops" +#!endif + +# HTable as a cache: +loadmodule "htable" + +#!ifdef WITH_DEBUG +#loadmodule "debugger.so" +modparam("debugger", "mod_hash_size", 5) +modparam("debugger", "mod_level_mode", 1) +modparam("debugger", "mod_level", "rtpengine=3") +modparam("debugger", "mod_level", "ims_qos=3") +modparam("debugger", "mod_level", "ims_ipsec_pcscf=3") +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") +modparam("debugger", "cfgtrace", 1) +#!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=600000;") +#!endif + +modparam("htable", "htable", "contact=>size=8;autoexpire=20") +modparam("htable", "htable", "a=>size=8;autoexpire=20") + +#!ifdef WITH_IMS_HDR_CACHE +modparam("htable", "htable", "serviceroutes=>size=16;autoexpire=14400;") +modparam("htable", "htable", "associateduris=>size=16;autoexpire=14400;") +#!endif + +#!ifdef WITH_NATPING +modparam("htable", "htable", "natping=>size=8;autoexpire=600000;") +modparam("htable", "htable", "natpingfail=>size=8;autoexpire=600000;") +modparam("htable", "htable", "natpingfrom=>size=8;autoexpire=600000;") +#!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=60;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", 36000) +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("htable", "htable", "ipsec_clients=>size=8;autoexpire=600000;") +#!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", 36000) +#!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") + + +####### Routing Logic ######## + +# 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); + + # 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|SUBSCRIBE|UPDATE|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; + } +# #!ifdef WITH_IPSEC +# if (!is_method("REGISTER")) { +# ipsec_forward("location"); +# } +# #!endif + # 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 ( is_method("ACK") && ($sht(contact=>$ci) != $null) ) { + xlog("Contact of Reply: $sht(contact=>$ci) ($ci)\n"); + $ru = $sht(contact=>$ci); + } + + 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("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")) { + xlog("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 + xlog("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)) > 30) { + 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 + #if ($sht(ipsec_clients=>$(T_req($ct){nameaddr.uri})) != $null) { + #ipsec_destroy("location"); + ipsec_destroy_by_contact("location", "$uac_req(ruri);$var(alias)", "$(uac_req(ouri){uri.host})", "$(uac_req(ouri){uri.port})"); + #} +#!endif + pcscf_unregister("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 location;", "resultset"); + xlog("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_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/images/kamailio-ims/pcscf/pcscf.cfg b/images/kamailio-ims/pcscf/pcscf.cfg new file mode 100644 index 0000000..4c5a050 --- /dev/null +++ b/images/kamailio-ims/pcscf/pcscf.cfg @@ -0,0 +1,125 @@ +# 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 + +# 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" + +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 + +#!subst "/NETWORKNAME/IMS_DOMAIN/" +#!subst "/HOSTNAME/pcscf.IMS_DOMAIN/" +#!subst "/PCRF_REALM/EPC_DOMAIN/" + +# 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_NAT +#!define WITH_NATPING +#!define FORCE_RTPRELAY +##!define WITH_TLS +##!define WITH_XMLRPC +##!define WITH_IPBLOCK +##!define WITH_ANTIFLOOD +#!define WITH_RX +#!define WITH_RX_REG +#!define WITH_RX_CALL +#!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/images/kamailio-ims/pcscf/pcscf.xml b/images/kamailio-ims/pcscf/pcscf.xml new file mode 100644 index 0000000..6179e2f --- /dev/null +++ b/images/kamailio-ims/pcscf/pcscf.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/images/kamailio-ims/pcscf/pcscf_init.sh b/images/kamailio-ims/pcscf/pcscf_init.sh new file mode 100755 index 0000000..9e58295 --- /dev/null +++ b/images/kamailio-ims/pcscf/pcscf_init.sh @@ -0,0 +1,129 @@ +#!/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. + +# Temporary patch to solve the case of docker internal dns not resolving "not running" container names. +# Just wait 10 seconds to be "running" and resolvable +sleep 10 + +MYSQL_IP=${MYSQL_IP:-"$(host -4 $MYSQL_HOSTNAME |awk '/has.*address/{print $NF; exit}')"} +export MYSQL_IP +echo "MYSQL_IP: $MYSQL_IP" + +PCSCF_IP=${PCSCF_IP:-"$(host -4 $PCSCF_HOSTNAME |awk '/has.*address/{print $NF; exit}')"} +export PCSCF_IP +echo "PCSCF_IP: $PCSCF_IP" + +RTPENGINE_IP=${RTPENGINE_IP:-"$(host -4 $RTPENGINE_HOSTNAME |awk '/has.*address/{print $NF; exit}')"} +export RTPENGINE_IP +echo "RTPENGINE_IP: $RTPENGINE_IP" + +UPF_IP=${UPF_IP:-"$(host -4 $UPF_HOSTNAME |awk '/has.*address/{print $NF; exit}')"} +export UPF_IP +echo "UPF_IP: $UPF_IP" + +DNS_IP=${DNS_IP:-"$(host -4 $DNS_HOSTNAME |awk '/has.*address/{print $NF; exit}')"} +export DNS_IP +echo "DNS_IP: $DNS_IP" + +if [ -z "$MYSQL_IP" ] \ + || [[ -z "$RTPENGINE_IP" ]] \ + || [[ -z "$PCSCF_IP" ]] \ + || [[ -z "$UPF_IP" ]] \ + || [[ -z "$DNS_IP" ]]; then +echo "Unable to resolve some IPs... restarting" +exit 1 +fi + +sh -c "echo 1 > /proc/sys/net/ipv4/ip_nonlocal_bind" +sh -c "echo 1 > /proc/sys/net/ipv6/ip_nonlocal_bind" + +EPC_DOMAIN=$EPC_DOMAIN +IMS_DOMAIN=$IMS_DOMAIN + +mkdir /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 VIA mysql_native_password USING PASSWORD('heslo')"; + mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'pcscf'@'$PCSCF_IP' IDENTIFIED VIA mysql_native_password USING PASSWORD('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 + +sed -i 's|PCSCF_IP|'$PCSCF_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|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|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 192.168.101.0/24 via ${UPF_IP} + +# Configure dns service as main nameserver +sleep 5 +ed /etc/resolv.conf << END +1i +nameserver ${DNS_IP} +. +w +q +END +cat /etc/resolv.conf diff --git a/images/kamailio-ims/pcscf/route/mo.cfg b/images/kamailio-ims/pcscf/route/mo.cfg new file mode 100644 index 0000000..a31a031 --- /dev/null +++ b/images/kamailio-ims/pcscf/route/mo.cfg @@ -0,0 +1,226 @@ +###################################################################### +# 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("Contact header: $ct\n"); + + # Process route headers, if any: + loose_route(); + if (!pcscf_is_registered("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("location", "$hdr(P-Preferred-Identity)")) { + append_hf("P-Asserted-Identity: $hdr(P-Preferred-Identity)\r\n"); + } else if (is_present_hf("P-Asserted-Identity") && pcscf_assert_identity("location", "$hdr(P-Asserted-Identity)")) { + append_hf("P-Asserted-Identity: $hdr(P-Asserted-Identity)\r\n"); + } else if (pcscf_assert_identity("location", "$(fu{tobody.uri})")) { + 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("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("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 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"); +} + +###################################################################### +# 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("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_IPSEC + #if ($sht(ipsec_clients=>$(T_req($ct){nameaddr.uri})) != $null) { + ipsec_forward("location"); + #} +#!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("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] +{ + #this is async so to know status we have to check the reply avp + 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] { + 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("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(); + } + + if ($dd != "" && $rd != "" && $fs != "") { + if ($rd =~ ".*" + $dd + ".*") { + ipsec_forward("location"); + } + } +} + +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("Contact header: $ct\n"); + + # In case of 1xx and 2xx do NAT + if(status=~"[12][0-9][0-9]") + route(NATMANAGE); + +#!ifdef WITH_RX + if (t_check_status("183|200") && has_body("application/sdp")) { + 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] +{ + #this is async so to know status we have to check the reply avp + 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 +} diff --git a/images/kamailio-ims/pcscf/route/mt.cfg b/images/kamailio-ims/pcscf/route/mt.cfg new file mode 100644 index 0000000..dc51ec0 --- /dev/null +++ b/images/kamailio-ims/pcscf/route/mt.cfg @@ -0,0 +1,150 @@ +###################################################################### +# 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("Contact header: $ct\n"); + set_dlg_profile("term"); +#!ifdef WITH_IPSEC + ipsec_forward("location"); +#!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("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_RX + if (t_check_status("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"); + + xlog("L_DBG", "About to test if this is a retransmitted reply which is still currently suspended\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"); + + #this is async so to know status we have to check the reply avp + 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] { + 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("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(); + } + + if ($dd != "" && $rd != "" && $fs != "") { + if ($rd =~ ".*" + $dd + ".*") { + ipsec_forward("location"); + } + } +} + +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("Contact header: $ct\n"); + # In case of 1xx and 2xx do NAT + if(status=~"[12][0-9][0-9]") + route(NATMANAGE); + +#!ifdef WITH_RX + if (t_check_status("183|200") && has_body("application/sdp")) { + 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] +{ + #this is async so to know status we have to check the reply avp + 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 +} diff --git a/images/kamailio-ims/pcscf/route/register.cfg b/images/kamailio-ims/pcscf/route/register.cfg new file mode 100644 index 0000000..2509424 --- /dev/null +++ b/images/kamailio-ims/pcscf/route/register.cfg @@ -0,0 +1,318 @@ +###################################################################### +# 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("location"); + } else { + send_reply("403", "No contact header"); + exit; + } + + $sht(ipsec_clients=>$(ct{nameaddr.uri})) = $null; + if ($hdr(Security-Client) =~ ".*ipsec-3gpp.*") { + $sht(ipsec_clients=>$(ct{nameaddr.uri})) = 1; + } + + # 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", "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("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 + #if ($sht(ipsec_clients=>$(T_req($ct){nameaddr.uri})) != $null) { + ipsec_forward("location"); + #} + } + else { + if (t_check_status("401")) { + ipsec_create("location"); + if ($sht(ipsec_clients=>$(T_req($ct){nameaddr.uri})) != $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"); + } + 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=\".*\"[,]/,/gi}); + $var(new_hdr) = $(var(new_hdr){re.subst,/[, ]*ik=\".*\"[,]/,/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"); + } + } + #if (t_check_status("403")) { + # ipsec_destroy("location"); + #} +#!endif + } + exit; +} + +# Negative replies to REGISTER requests: +###################################################################### +failure_route[REGISTER_failure] +{ +#!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; + } +} diff --git a/images/kamailio-ims/pcscf/route/rtp.cfg b/images/kamailio-ims/pcscf/route/rtp.cfg new file mode 100644 index 0000000..d2566ec --- /dev/null +++ b/images/kamailio-ims/pcscf/route/rtp.cfg @@ -0,0 +1,208 @@ +# 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 + + 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/images/kamailio-ims/pcscf/route/websocket.cfg b/images/kamailio-ims/pcscf/route/websocket.cfg new file mode 100644 index 0000000..1f5b70f --- /dev/null +++ b/images/kamailio-ims/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/images/kamailio-ims/pcscf/route/xmlrpc.cfg b/images/kamailio-ims/pcscf/route/xmlrpc.cfg new file mode 100644 index 0000000..50571c0 --- /dev/null +++ b/images/kamailio-ims/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/images/kamailio-ims/pcscf/sems/etc/methodmap.conf b/images/kamailio-ims/pcscf/sems/etc/methodmap.conf new file mode 100644 index 0000000..8641a01 --- /dev/null +++ b/images/kamailio-ims/pcscf/sems/etc/methodmap.conf @@ -0,0 +1,2 @@ +OPTIONS=>refuse_with_200 +REGISTER=>register diff --git a/images/kamailio-ims/pcscf/sems/etc/mo.sbcprofile.conf b/images/kamailio-ims/pcscf/sems/etc/mo.sbcprofile.conf new file mode 100644 index 0000000..39a2527 --- /dev/null +++ b/images/kamailio-ims/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/images/kamailio-ims/pcscf/sems/etc/monitoring.conf b/images/kamailio-ims/pcscf/sems/etc/monitoring.conf new file mode 100644 index 0000000..b61c1ca --- /dev/null +++ b/images/kamailio-ims/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/images/kamailio-ims/pcscf/sems/etc/mt.sbcprofile.conf b/images/kamailio-ims/pcscf/sems/etc/mt.sbcprofile.conf new file mode 100644 index 0000000..fac9d2c --- /dev/null +++ b/images/kamailio-ims/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/images/kamailio-ims/pcscf/sems/etc/nocache.sbcprofile.conf b/images/kamailio-ims/pcscf/sems/etc/nocache.sbcprofile.conf new file mode 100644 index 0000000..ec3262d --- /dev/null +++ b/images/kamailio-ims/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/images/kamailio-ims/pcscf/sems/etc/refuse.sbcprofile.conf b/images/kamailio-ims/pcscf/sems/etc/refuse.sbcprofile.conf new file mode 100644 index 0000000..3ea3d62 --- /dev/null +++ b/images/kamailio-ims/pcscf/sems/etc/refuse.sbcprofile.conf @@ -0,0 +1 @@ +refuse_with="403 Forbidden" diff --git a/images/kamailio-ims/pcscf/sems/etc/refuse_with_200.sbcprofile.conf b/images/kamailio-ims/pcscf/sems/etc/refuse_with_200.sbcprofile.conf new file mode 100644 index 0000000..de0a306 --- /dev/null +++ b/images/kamailio-ims/pcscf/sems/etc/refuse_with_200.sbcprofile.conf @@ -0,0 +1 @@ +refuse_with="200 OK" diff --git a/images/kamailio-ims/pcscf/sems/etc/register.sbcprofile.conf b/images/kamailio-ims/pcscf/sems/etc/register.sbcprofile.conf new file mode 100644 index 0000000..c8f1ae2 --- /dev/null +++ b/images/kamailio-ims/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/images/kamailio-ims/pcscf/sems/etc/rurimap.conf b/images/kamailio-ims/pcscf/sems/etc/rurimap.conf new file mode 100644 index 0000000..867ad7e --- /dev/null +++ b/images/kamailio-ims/pcscf/sems/etc/rurimap.conf @@ -0,0 +1 @@ +ims.voiceblue.com=>mo diff --git a/images/kamailio-ims/pcscf/sems/etc/sbc.conf b/images/kamailio-ims/pcscf/sems/etc/sbc.conf new file mode 100644 index 0000000..dd206a5 --- /dev/null +++ b/images/kamailio-ims/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/images/kamailio-ims/pcscf/sems/etc/stats.conf b/images/kamailio-ims/pcscf/sems/etc/stats.conf new file mode 100644 index 0000000..57babe1 --- /dev/null +++ b/images/kamailio-ims/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/images/kamailio-ims/pcscf/sems/etc/xmlrpc2di.conf b/images/kamailio-ims/pcscf/sems/etc/xmlrpc2di.conf new file mode 100644 index 0000000..9c9bf05 --- /dev/null +++ b/images/kamailio-ims/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/images/kamailio-ims/pcscf/sems/sems.conf b/images/kamailio-ims/pcscf/sems/sems.conf new file mode 100644 index 0000000..ecae29e --- /dev/null +++ b/images/kamailio-ims/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=