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 <marielena.mmb@gmail.com>
This commit is contained in:
Marielena Márquez
2022-10-03 11:08:45 +02:00
committed by GitHub
parent 9b7663def0
commit 0b3f111928
73 changed files with 10120 additions and 0 deletions

View File

@@ -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
```

View File

@@ -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!" .

View File

@@ -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

View File

@@ -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

View File

@@ -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";
};

View File

@@ -0,0 +1,9 @@
[mysqld]
user = mysql
bind-address = 0.0.0.0
#
# * Fine Tuning
#
key_buffer_size = 16M
max_connections = 250

View File

@@ -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;"

View File

@@ -0,0 +1,3 @@
[mysql]
user=root
password=ims

View File

@@ -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

View File

@@ -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 = "<x509 certif file.PEM>" , "<x509 private key file.PEM>";
#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 = "<file.PEM>";
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 = "<file.PEM>";
# 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 = "<file.PEM>";
##############################################################
## 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; };
##############################################################

View File

@@ -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:

View File

@@ -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 = "<x509 certif file.PEM>" , "<x509 private key file.PEM>";
#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 = "<file.PEM>";
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 = "<file.PEM>";
# 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 = "<file.PEM>";
##############################################################
## 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; };
##############################################################

View File

@@ -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 = "<x509 certif file.PEM>" , "<x509 private key file.PEM>";
#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 = "<file.PEM>";
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 = "<file.PEM>";
# 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 = "<file.PEM>";
##############################################################
## 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; };
##############################################################

View File

@@ -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:

View File

@@ -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:

View File

@@ -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

View File

@@ -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;
};
};
};
}
);

View File

@@ -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
);

View File

@@ -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
);
}
);
};

View File

@@ -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: {}

View File

@@ -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

View File

@@ -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())

80
images/fhoss/Dockerfile Normal file
View File

@@ -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

View File

@@ -0,0 +1,3 @@
IMAGE_TAG=develop
#comma separated list of platforms. If empty, image will not be multiarch.
PLATFORMS=linux/amd64

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- HSS Server config -->
<DiameterPeer
FQDN="hss.${IMS_DOMAIN}"
Realm="${IMS_DOMAIN}"
Vendor_Id="10415"
Product_Name="JavaDiameterPeer"
AcceptUnknownPeers="1"
DropUnknownOnDisconnect="1"
Tc="30"
Workers="4"
QueueLength="32"
>
<Peer FQDN="icscf.${IMS_DOMAIN}" Realm="${IMS_DOMAIN}" port="3869" />
<Peer FQDN="scscf.${IMS_DOMAIN}" Realm="${IMS_DOMAIN}" port="3870" />
<Acceptor port="3868" bind="${FHOSS_IP}" />
<Auth id="16777216" vendor="10415"/><!-- 3GPP Cx -->
<Auth id="16777216" vendor="4491"/><!-- CableLabs Cx -->
<Auth id="16777216" vendor="13019"/><!-- ETSI/TISPAN Cx -->
<Auth id="16777216" vendor="0"/><!-- ETSI/TISPAN Cx -->
<Auth id="16777217" vendor="10415"/><!-- 3GPP Sh -->
<Auth id="16777221" vendor="10415"/>
</DiameterPeer>

View File

@@ -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

View File

@@ -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

View File

@@ -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

18
images/fhoss/resources/hss.sh Executable file
View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<DiameterPeer
FQDN="icscf.IMS_DOMAIN"
Realm="IMS_DOMAIN"
Vendor_Id="10415"
Product_Name="CDiameterPeer"
AcceptUnknownPeers="1"
DropUnknownOnDisconnect="1"
Tc="30"
Workers="16"
QueueLength="32"
TransactionTimeout="5"
SessionsHashSize="128"
DefaultAuthSessionTimeout="3600"
MaxAuthSessionTimeout="3600"
>
<Peer FQDN="hss.IMS_DOMAIN" Realm="IMS_DOMAIN" port="3868"/>
<Acceptor port="3869" bind="ICSCF_IP"/>
<Auth id="16777216" vendor="10415"/><!-- 3GPP Cx -->
<Auth id="16777216" vendor="4491"/><!-- CableLabs Cx -->
<Auth id="16777216" vendor="13019"/><!-- ETSI/TISPAN Cx -->
<Auth id="16777216" vendor="0"/><!-- ETSI/TISPAN Cx -->
<!--
Supported Vendor IDs - list of values which will be sent in the CER/CEA in the
Supported-Vendor-ID AVPs
-->
<SupportedVendor vendor="10415" />
<DefaultRoute FQDN="hss.IMS_DOMAIN" metric="10"/>
</DiameterPeer>

View File

@@ -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

View File

@@ -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: <sr-users@lists.kamailio.org>.
#
# 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

View File

@@ -0,0 +1,3 @@
IMAGE_TAG=5.3-dev
#comma separated list of platforms. If empty, image will not be multiarch.
PLATFORMS=linux/amd64

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1 @@
# SBC's

View File

@@ -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: <sip:term@$Ri:$Rp;lr>\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"

View File

@@ -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

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<DiameterPeer
FQDN="pcscf.IMS_DOMAIN"
Realm="IMS_DOMAIN"
Vendor_Id="10415"
Product_Name="CDiameterPeer"
AcceptUnknownPeers="1"
DropUnknownOnDisconnect="1"
Tc="30"
Workers="4"
QueueLength="8"
TransactionTimeout="5"
SessionsHashSize="128"
DefaultAuthSessionTimeout="3600"
MaxAuthSessionTimeout="3600"
>
<Peer FQDN="pcrf.EPC_DOMAIN" Realm="EPC_DOMAIN" port="3868"/>
<Acceptor port="3871" bind="PCSCF_IP"/>
<Auth id="16777236" vendor="10415"/> <!-- 3GPP Rx -->
<Auth id="16777236" vendor="0"/> <!-- 3GPP Rx -->
<DefaultRoute FQDN="pcrf.EPC_DOMAIN" metric="10"/>
</DiameterPeer>

View File

@@ -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

View File

@@ -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=\"<sip:$var(trf);lr>\"\r\n");
} else {
append_hf("Feature-Caps: *;+g.3gpp.trf=\"<sip:$var(trf);lr>\"\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
}

View File

@@ -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
}

View File

@@ -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: <sip:term@HOSTNAME;lr>\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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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", "<html><body>Wrong URL $hu</body></html>");
xhttp_reply("404", "Not Found", "", "");
}
event_route[websocket:closed] {
xlog("L_DBG", "WebSocket connection from $si:$sp has closed\n");
}

View File

@@ -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;
}

View File

@@ -0,0 +1,2 @@
OPTIONS=>refuse_with_200
REGISTER=>register

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1 @@
refuse_with="403 Forbidden"

View File

@@ -0,0 +1 @@
refuse_with="200 OK"

View File

@@ -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

View File

@@ -0,0 +1 @@
ims.voiceblue.com=>mo

View File

@@ -0,0 +1,62 @@
# profiles - comma-separated list of call profiles to load
#
# <name>.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=<profile_name> always use <profile_name>
#
# 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

View File

@@ -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

View File

@@ -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
#

View File

@@ -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=<ip_address>|<device>
#
# - 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=<ip_address>|<device>
#
# - 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=<ip_address>
#
# - 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=<port_number>
#
# - 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=<port>
#
# - sets lowest for RTP used port
rtp_low_port=10000
# optional parameter: rtp_high_port=<port>
#
# - sets highest for RTP used port
rtp_high_port=19999
# Additional IFs (optional):
# additional_interfaces = <list of 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=<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=<modules list>
#
# 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=<modules list>
#
# 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> - 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=<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=<payload list>
#
# 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=<time in seconds>
#
# Limit on server shutdown time (time to send/resend BYE
# to active calls). 0 to disable (infinite).
#
# Default: 10
#
max_shutdown_time = 60
# optional parameter: shutdown_mode_reply="<code> <reason>"
#
# Error reply that is used as reply to INVITE and OPTION
# when SEMS is shutting down.
#
# Default: shutdown_mode_reply="503 Server shutting down"
############################################################
# tuning
# optional parameter: session_processor_threads=<num_value>
#
# - controls how many threads should be created that
# process the application logic and in-dialog signaling.
# This is only available if compiled with threadpool support!
# (set USE_THREADPOOL in Makefile.defs)
# Defaults to 10
#
# session_processor_threads=50
# optional parameter: media_processor_threads=<num_value>
#
# - controls how many threads should be created that
# process media - on single-processor systems set this
# parameter to 1 (default), on MP systems to a higher
# value
#
# media_processor_threads=1
# optional parameter: session_limit=<limit>;<err code>;<err reason>
#
# - this sets a maximum active session limit. If that limit is
# reached, no further calls are accepted, but the error reply
# with err code/err reason is sent out.
#
# Default: 0 (None)
#
# Example:
# session_limit="1000;503;Server overload"
# optional parameter: options_session_limit=<limit>;<err code>;<err reason>
#
# - this sets a custom response to OPTIONS, if the session count reaches
# a certain limit. This way health monitor could raise an alarm to syste
# administrator.
#
# Default: 0 (None)
#
# Example:
# options_session_limit="900;503;Warning, server soon overloaded"
# optional parameter: dead_rtp_time=<unsigned int>
#
# - if != 0, after this time (in seconds) of no RTP
# a session is considered dead and stopped. If set
# to 0 no check is done for rtp timeout.
#
# default=300 (5 minutes)
#
# Examples:
# # disable RTP timeout
# dead_rtp_time=0
# # RTP timeout after 10 seconds
# dead_rtp_time=10
# optional parameter: use_default_signature={yes|no}
#
# - use a Server/User-Agent header with the SEMS server
# signature and version.
# Set server_signature=0 in ser_sems.cfg if you use SER
# as SIP stack.
#
# default=no
#
use_default_signature=yes
# optional parameter: signature=<signature string>
#
# - use a Server/User-Agent header with a custom user agent
# signature.
# Overridden by default signature if
# use_default_signature is set.
# Set server_signature=0 in ser_sems.cfg if you use it.
#
#
# signature="SEMS media server 1.0"
# optional parameter: single_codec_in_ok={yes|no}
#
# - use single codec in 200 OK response
#
# default=no
#
# single_codec_in_ok=no
# optional parameter: codec_order=codec_name_1,codec_name2,...
#
# - Codec order used when sending INVITE requests. Codecs in codec_order
# will be on the top of the list followed by other supported codecs
# (if any).
#
# default=empty
#
# codec_order=iLBC,GSM
# optional parameter: ignore_rtpxheaders={yes|no}
#
# - if this is set to yes, RTP extension headers (e.g. when using ZRTP)
# are ignored. If set to no, the whole RTP packets with extension
# headers will be ignored and a debug message is printed on every
# received packet.
#
# default=no
#
# ignore_rtpxheaders=yes
# optional parameter: dtmf_detector={spandsp|internal}
#
# sets inband DTMF detector to use. spandsp support must be compiled in
# for this to have effect if dtmf_detector=spandsp.
#
# default: internal
#
# dtmf_detector=spandsp
# optional parameter: wait_for_bye_transaction={yes|no}
#
# when SEMS stops a call sending BYE as UAC, this option sets whether
# SEMS waits for the BYE transaction to finish before forgetting the call.
# This may be necessary e.g. to authenticate the BYE request.
#
# default: no
#
# wait_for_bye_transaction=yes
# optional parameter: unhandled_reply_loglevel={error|warn|info|debug|no}
#
# the default application logic implemented in the applications is to stop
# the session right after sending BYE, without waiting for a reply. this
# leads to many log entries of the form
# ERROR: [b6fa6bb0] handleSipMsg (AmSipDispatcher.cpp:48): unhandled
# reply: [code:200;phrase:[OK];... ]
#
# This parameter sets the log lovel of unhandled positive (200 class) replies.
#
# default: error
#
# unhandled_reply_loglevel=info
############################################################
# SIP stack settings
# default settings (i.e. leave out) for these should be OK
# for most applications
# skip DNS SRV lookup? [yes, no]
#
# according to RFC, if no port is specified, destination IP address
# should be resolved with a DNS SRV lookup. If SEMS should not do that
# (only an A record lookup), set disable_dns_srv=yes.
#
# Default: no
#
#disable_dns_srv=yes
# support 100rel (PRACK) extension (RFC3262)? [disabled|supported|require]
#
# disabled - disable support for 100rel
# supported - support it if remote end does, default
# require - required
#
# Default: supported
#
#100rel=require
# Make SIP authenticated requests sticky to the proxy? [yes | no]
#
# If enabled, host of request-URI of out-of-dialog requests that are
# authenticated with SIP auth is changed to the previously resolved
# next-hop IP:port.
#
# default: no
#
# proxy_sticky_auth=yes
#
# Accept final replies without To-tag? [yes|no]
#
#accept_fr_without_totag=yes
#
# Log raw messages? [no|debug|info|warn|error]
#
# Default: debug
#
#log_raw_messages=no
#
# Log parsed received messages? [yes|no]
#
# Default: yes
#
#log_parsed_messages=no
# SIP UDP socket receive buffer size (in bytes)
#
# if not set, system default is used (which usually
# is modest). set sytem wide upper limit with
# e.g. sysctl -w net.core.rmem_max=8388608
#
# udp_rcvbuf = <value>
# Number of SIP UDP receiver threads
#
# Default: 4
#
# sip_server_threads=8
#
# accept forked dialogs on UAS side? [yes|no]
#
# no - INVITE with existing callid+remote_tag is replied with 482.
# yes - INVITE with existing callid+remote_tag+via_branch is replied with 482.
# Forked INVITEs (!= via-branch) are accepted.
#
# Default: yes
#
accept_forked_dialogs=yes

View File

@@ -0,0 +1,15 @@
#
# TLS Configuration File
#
# This is the default server domain, settings
# in this domain will be used for all incoming
# connections that do not match any other server
# domain in this configuration file.
#
[server:default]
method = SSLv23
verify_certificate = no
require_certificate = no
private_key = /etc/kamailio/kamailio-selfsigned.key
certificate = /etc/kamailio/kamailio-selfsigned.pem

View File

@@ -0,0 +1,293 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="tPriority" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tProfilePartIndicator" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">REGISTERED</label>
<definition xml:lang="en">iFC is part of the registered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">UNREGISTERED</label>
<definition xml:lang="en">iFC is part of the unregistered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tSharedIFCSetID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tGroupID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tRegistrationType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="2"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">INITIAL_REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to initial registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">RE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to re-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to de-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDefaultHandling" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_CONTINUED</label>
<definition xml:lang="en">Session Continued</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_TERMINATED</label>
<definition xml:lang="en">Session Terminated</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDirectionOfRequest" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="3"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">ORIGINATING_SESSION</label>
<definition xml:lang="en">Originating Session</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_REGISTERED</label>
<definition xml:lang="en">Terminating Session for registered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_UNREGISTERED</label>
<definition xml:lang="en">Terminating Session for unregistered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tPrivateID" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tSIP_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tTEL_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tIdentity" final="list restriction">
<xs:union memberTypes="tSIP_URL tTEL_URL"/>
</xs:simpleType>
<xs:simpleType name="tIdentityType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="2"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">PUBLIC_USER_IDENTITY</label>
<definition xml:lang="en">Identity is a Public User Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DISTINCT_PSI</label>
<definition xml:lang="en">Identity is a distinct Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">WILDCARDED_PSI</label>
<definition xml:lang="en">Identity matches a wildcarded Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tPublicIdentityExtension">
<xs:sequence>
<xs:element name="IdentityType" type="tIdentityType" minOccurs="0"/>
<xs:element name="WildcardedPSI" type="xs:anyURI" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="tServiceInfo" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tString" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tBool">
<xs:restriction base="xs:boolean"/>
</xs:simpleType>
<xs:simpleType name="tSubscribedMediaProfileId" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tExtension">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfileExtension">
<xs:sequence>
<xs:element name="SharedIFCSetID" type="tSharedIFCSetID" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTriExtension">
<xs:sequence>
<xs:element name="RegistrationType" type="tRegistrationType" minOccurs="0" maxOccurs="2"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tIMSSubscription">
<xs:sequence>
<xs:element name="PrivateID" type="tPrivateID"/>
<xs:element name="ServiceProfile" type="tServiceProfile" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfile">
<xs:sequence>
<xs:element name="PublicIdentity" type="tPublicIdentity" maxOccurs="unbounded"/>
<xs:element name="CoreNetworkServicesAuthorization" type="tCoreNetworkServicesAuthorization" minOccurs="0" />
<xs:element name="InitialFilterCriteria" type="tInitialFilterCriteria" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tServiceProfileExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tCoreNetworkServicesAuthorization">
<xs:sequence>
<xs:element name="SubscribedMediaProfileId" type="tSubscribedMediaProfileId" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tInitialFilterCriteria">
<xs:sequence>
<xs:element name="Priority" type="tPriority"/>
<xs:element name="TriggerPoint" type="tTrigger" minOccurs="0"/>
<xs:element name="ApplicationServer" type="tApplicationServer"/>
<xs:element name="ProfilePartIndicator" type="tProfilePartIndicator" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tTrigger">
<xs:sequence>
<xs:element name="ConditionTypeCNF" type="tBool"/>
<xs:element name="SPT" type="tSePoTri" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTri">
<xs:sequence>
<xs:element name="ConditionNegated" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Group" type="tGroupID" maxOccurs="unbounded"/>
<xs:choice>
<xs:element name="RequestURI" type="tString"/>
<xs:element name="Method" type="tString"/>
<xs:element name="SIPHeader" type="tHeader"/>
<xs:element name="SessionCase" type="tDirectionOfRequest"/>
<xs:element name="SessionDescription" type="tSessionDescription"/>
</xs:choice>
<xs:element name="Extension" type="tSePoTriExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tHeader">
<xs:sequence>
<xs:element name="Header" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSessionDescription">
<xs:sequence>
<xs:element name="Line" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tApplicationServer">
<xs:sequence>
<xs:element name="ServerName" type="tSIP_URL"/>
<xs:element name="DefaultHandling" type="tDefaultHandling" minOccurs="0"/>
<xs:element name="ServiceInfo" type="tServiceInfo" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tPublicIdentity">
<xs:sequence>
<xs:element name="BarringIndication" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Identity" type="tIdentity"/>
<xs:element name="Extension" type="tPublicIdentityExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="IMSSubscription" type="tIMSSubscription"/>
</xs:schema>

View File

@@ -0,0 +1,301 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="tPriority" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tProfilePartIndicator" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">REGISTERED</label>
<definition xml:lang="en">iFC is part of the registered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">UNREGISTERED</label>
<definition xml:lang="en">iFC is part of the unregistered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tSharedIFCSetID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tGroupID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tRegistrationType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="2"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">INITIAL_REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to initial registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">RE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to re-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to de-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDefaultHandling" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_CONTINUED</label>
<definition xml:lang="en">Session Continued</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_TERMINATED</label>
<definition xml:lang="en">Session Terminated</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDirectionOfRequest" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="3"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">ORIGINATING_SESSION</label>
<definition xml:lang="en">Originating Session</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_REGISTERED</label>
<definition xml:lang="en">Terminating Session for registered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_UNREGISTERED</label>
<definition xml:lang="en">Terminating Session for unregistered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="3">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">ORIGINATING_UNREGISTERED</label>
<definition xml:lang="en">Originating Session for an unregistered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tPrivateID" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tSIP_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tTEL_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tIdentity" final="list restriction">
<xs:union memberTypes="tSIP_URL tTEL_URL"/>
</xs:simpleType>
<xs:simpleType name="tIdentityType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="2"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">PUBLIC_USER_IDENTITY</label>
<definition xml:lang="en">Identity is a Public User Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DISTINCT_PSI</label>
<definition xml:lang="en">Identity is a distinct Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">WILDCARDED_PSI</label>
<definition xml:lang="en">Identity matches a wildcarded Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tPublicIdentityExtension">
<xs:sequence>
<xs:element name="IdentityType" type="tIdentityType" minOccurs="0"/>
<xs:element name="WildcardedPSI" type="xs:anyURI" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="tServiceInfo" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tString" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tBool">
<xs:restriction base="xs:boolean"/>
</xs:simpleType>
<xs:simpleType name="tSubscribedMediaProfileId" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tExtension">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfileExtension">
<xs:sequence>
<xs:element name="SharedIFCSetID" type="tSharedIFCSetID" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTriExtension">
<xs:sequence>
<xs:element name="RegistrationType" type="tRegistrationType" minOccurs="0" maxOccurs="2"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tIMSSubscription">
<xs:sequence>
<xs:element name="PrivateID" type="tPrivateID"/>
<xs:element name="ServiceProfile" type="tServiceProfile" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfile">
<xs:sequence>
<xs:element name="PublicIdentity" type="tPublicIdentity" maxOccurs="unbounded"/>
<xs:element name="CoreNetworkServicesAuthorization" type="tCoreNetworkServicesAuthorization" minOccurs="0"/>
<xs:element name="InitialFilterCriteria" type="tInitialFilterCriteria" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tServiceProfileExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tCoreNetworkServicesAuthorization">
<xs:sequence>
<xs:element name="SubscribedMediaProfileId" type="tSubscribedMediaProfileId" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tInitialFilterCriteria">
<xs:sequence>
<xs:element name="Priority" type="tPriority"/>
<xs:element name="TriggerPoint" type="tTrigger" minOccurs="0"/>
<xs:element name="ApplicationServer" type="tApplicationServer"/>
<xs:element name="ProfilePartIndicator" type="tProfilePartIndicator" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tTrigger">
<xs:sequence>
<xs:element name="ConditionTypeCNF" type="tBool"/>
<xs:element name="SPT" type="tSePoTri" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTri">
<xs:sequence>
<xs:element name="ConditionNegated" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Group" type="tGroupID" maxOccurs="unbounded"/>
<xs:choice>
<xs:element name="RequestURI" type="tString"/>
<xs:element name="Method" type="tString"/>
<xs:element name="SIPHeader" type="tHeader"/>
<xs:element name="SessionCase" type="tDirectionOfRequest"/>
<xs:element name="SessionDescription" type="tSessionDescription"/>
</xs:choice>
<xs:element name="Extension" type="tSePoTriExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tHeader">
<xs:sequence>
<xs:element name="Header" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSessionDescription">
<xs:sequence>
<xs:element name="Line" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tApplicationServer">
<xs:sequence>
<xs:element name="ServerName" type="tSIP_URL"/>
<xs:element name="DefaultHandling" type="tDefaultHandling" minOccurs="0"/>
<xs:element name="ServiceInfo" type="tServiceInfo" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tPublicIdentity">
<xs:sequence>
<xs:element name="BarringIndication" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Identity" type="tIdentity"/>
<xs:element name="Extension" type="tPublicIdentityExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="IMSSubscription" type="tIMSSubscription"/>
</xs:schema>

View File

@@ -0,0 +1,379 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="tPriority" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tProfilePartIndicator" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">REGISTERED</label>
<definition xml:lang="en">iFC is part of the registered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">UNREGISTERED</label>
<definition xml:lang="en">iFC is part of the unregistered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tSharedIFCSetID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tGroupID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tRegistrationType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="2"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">INITIAL_REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to initial registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">RE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to re-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to de-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDefaultHandling" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_CONTINUED</label>
<definition xml:lang="en">Session Continued</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_TERMINATED</label>
<definition xml:lang="en">Session Terminated</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDirectionOfRequest" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="3"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">ORIGINATING_SESSION</label>
<definition xml:lang="en">Originating Session</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_REGISTERED</label>
<definition xml:lang="en">Terminating Session for registered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_UNREGISTERED</label>
<definition xml:lang="en">Terminating Session for unregistered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="3">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">ORIGINATING_UNREGISTERED</label>
<definition xml:lang="en">Originating Session for an unregistered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tPrivateID" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tSIP_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tTEL_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tIdentity" final="list restriction">
<xs:union memberTypes="tSIP_URL tTEL_URL"/>
</xs:simpleType>
<xs:simpleType name="tIdentityType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="4"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">PUBLIC_USER_IDENTITY</label>
<definition xml:lang="en">Identity is a Public User Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DISTINCT_PSI</label>
<definition xml:lang="en">Identity is a distinct Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">WILDCARDED_PSI</label>
<definition xml:lang="en">Identity matches a wildcarded Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="3">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">WILDCARDED_IMPU</label>
<definition xml:lang="en">Identity is a Wildcarded Public User Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="4">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">IMPU WILDCARD</label>
<definition xml:lang="en">Identity is a Wildcard for Public User Identities.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tPublicIdentityExtension">
<xs:sequence>
<xs:element name="IdentityType" type="tIdentityType" minOccurs="0"/>
<xs:element name="WildcardedPSI" type="xs:anyURI" minOccurs="0"/>
<xs:element name="Extension" type="tPublicIdentityExtension2" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tPublicIdentityExtension2">
<xs:sequence>
<xs:element name="DisplayName" type="tDisplayName" minOccurs="0"/>
<xs:element name="AliasIdentityGroupID" type="tAliasIdentityGroupID" minOccurs="0"/>
<xs:element name="Extension" type="tPublicIdentityExtension3" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tPublicIdentityExtension3">
<xs:sequence>
<xs:element name="WildcardedIMPU" type="xs:anyURI" minOccurs="0"/>
<xs:element name="ServiceLevelTraceInfo" type="tServiceLevelTraceInfo" minOccurs="0"/>
<xs:element name="SIPURIParameters" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="tDisplayName" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tAliasIdentityGroupID" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tServiceLevelTraceInfo" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tServiceInfo" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tString" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tBool">
<xs:restriction base="xs:boolean"/>
</xs:simpleType>
<xs:simpleType name="tSubscribedMediaProfileId" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tExtension">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfileExtension">
<xs:sequence>
<xs:element name="SharedIFCSetID" type="tSharedIFCSetID" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTriExtension">
<xs:sequence>
<xs:element name="RegistrationType" type="tRegistrationType" minOccurs="0" maxOccurs="2"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tListOfServiceIds">
<xs:sequence>
<xs:element name="ServiceId" type="tString" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tCNServicesAuthorizationExtension">
<xs:sequence>
<xs:element name="ListOfServiceIds" type="tListOfServiceIds" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tIMSSubscription">
<xs:sequence>
<xs:element name="PrivateID" type="tPrivateID"/>
<xs:element name="ServiceProfile" type="tServiceProfile" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfile">
<xs:sequence>
<xs:element name="PublicIdentity" type="tPublicIdentity" maxOccurs="unbounded"/>
<xs:element name="CoreNetworkServicesAuthorization" type="tCoreNetworkServicesAuthorization" minOccurs="0"/>
<xs:element name="InitialFilterCriteria" type="tInitialFilterCriteria" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tServiceProfileExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tCoreNetworkServicesAuthorization">
<xs:sequence>
<xs:element name="SubscribedMediaProfileId" type="tSubscribedMediaProfileId" minOccurs="0"/>
<xs:element name="Extension" type="tCNServicesAuthorizationExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tInitialFilterCriteria">
<xs:sequence>
<xs:element name="Priority" type="tPriority"/>
<xs:element name="TriggerPoint" type="tTrigger" minOccurs="0"/>
<xs:element name="ApplicationServer" type="tApplicationServer"/>
<xs:element name="ProfilePartIndicator" type="tProfilePartIndicator" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tTrigger">
<xs:sequence>
<xs:element name="ConditionTypeCNF" type="tBool"/>
<xs:element name="SPT" type="tSePoTri" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTri">
<xs:sequence>
<xs:element name="ConditionNegated" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Group" type="tGroupID" maxOccurs="unbounded"/>
<xs:choice>
<xs:element name="RequestURI" type="tString"/>
<xs:element name="Method" type="tString"/>
<xs:element name="SIPHeader" type="tHeader"/>
<xs:element name="SessionCase" type="tDirectionOfRequest"/>
<xs:element name="SessionDescription" type="tSessionDescription"/>
</xs:choice>
<xs:element name="Extension" type="tSePoTriExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tHeader">
<xs:sequence>
<xs:element name="Header" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSessionDescription">
<xs:sequence>
<xs:element name="Line" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tApplicationServer">
<xs:sequence>
<xs:element name="ServerName" type="tSIP_URL"/>
<xs:element name="DefaultHandling" type="tDefaultHandling" minOccurs="0"/>
<xs:element name="ServiceInfo" type="tServiceInfo" minOccurs="0"/>
<xs:element name="Extension" type="tApplicationServerExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tPublicIdentity">
<xs:sequence>
<xs:element name="BarringIndication" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Identity" type="tIdentity"/>
<xs:element name="Extension" type="tPublicIdentityExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tApplicationServerExtension">
<xs:sequence>
<xs:element name="IncludeRegisterRequest" type="tIncludeRegisterRequest" minOccurs="0" maxOccurs="1"/>
<xs:element name="IncludeRegisterResponse" type="tIncludeRegisterResponse" minOccurs="0" maxOccurs="1"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tIncludeRegisterRequest">
<xs:sequence>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tIncludeRegisterResponse">
<xs:sequence>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="IMSSubscription" type="tIMSSubscription"/>
</xs:schema>

View File

@@ -0,0 +1 @@
# ng-voice Interconnect

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,84 @@
# SIP / UDP
listen=udp:SCSCF_IP:6060
# SIP / TCP
listen=tcp:SCSCF_IP:6060
# SIP / TCP/TLS
#listen=tls:SCSCF_IP:6061
#!define NETWORKNAME "IMS_DOMAIN"
#!define NETWORKNAME_ESC "IMS_SLASH_DOMAIN"
#!define HOSTNAME "scscf.IMS_DOMAIN"
#!define HOSTNAME_ESC "scscf\.IMS_SLASH_DOMAIN"
#!define URI "sip:scscf.IMS_DOMAIN:6060"
#!subst "/NETWORKNAME/IMS_DOMAIN/"
alias=scscf.IMS_DOMAIN
# ENUM-Server to query:
#!define ENUM_SUFFIX "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:
# For use with a single database:
#!define DB_URL "mysql://scscf:heslo@MYSQL_IP/scscf"
# For use with DB_Cluster: con1 (primary), con2 (backup)
##!define DB_URL "con1=>mysql://scscf:heslo@MYSQL_IP/scscf"
##!define DB_URL2 "con2=>mysql://scscf:heslo@MYSQL_IP/scscf"
# Select Authorization Algorhithm:
##!define REG_AUTH_DEFAULT_ALG "AKAv1-MD5"
##!define REG_AUTH_DEFAULT_ALG "AKAv2-MD5"
##!define REG_AUTH_DEFAULT_ALG "MD5"
##!define REG_AUTH_DEFAULT_ALG "CableLabs-Digest"
##!define REG_AUTH_DEFAULT_ALG "3GPP-Digest"
##!define REG_AUTH_DEFAULT_ALG "TISPAN-HTTP_DIGEST_MD5"
# Let the HSS decide
#!define REG_AUTH_DEFAULT_ALG "HSS-Selected"
# Number of TCP Processes
#!define TCP_PROCESSES 3
##!define RO_FORCED_PEER "32260@3gpp.org"
#!define RO_DESTINATION "hssocs.voiceblue.com"
#!define RO_ROOT "32260@3gpp.org"
#!define RO_EXT "ext"
#!define RO_MNC "02"
#!define RO_MCC "001"
#(see https://en.wikipedia.org/wiki/Mobile_country_code_(MCC))
#!define RO_RELEASE "8"
# See http://tools.ietf.org/html/rfc4006#section-4.1.2 for the definition of the Service-Context
##!define XMLRPC_WHITELIST_1 "127.0.0.1"
##!define XMLRPC_WHITELIST_2 "127.0.0.1"
##!define XMLRPC_WHITELIST_3 "127.0.0.1"
# Several features can be enabled using '#!define WITH_FEATURE' directives:
#
# *** To run in debug mode:
# - define WITH_DEBUG
#
# *** To enable TCP support execute:
# - define WITH_TCP
#
# *** To enable XMLRPC support execute:
# - define WITH_XMLRPC
# - this will automagically enable TCP
#
# *** To enable the Ro-Interface:
# - Configure Ro-Diameter-Interface in scscf.xml
# - define WITH_RO
#
# *** To enable a Homer SIP-Capter-Node:
# - define CAPTURE_NODE with a proper address
#
# Enabled Features for this host:
##!define WITH_DEBUG
#!define WITH_TCP
##!define WITH_XMLRPC
##!define WITH_RO
##!define WITH_RO_TERM
#!define WITH_AUTH

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<DiameterPeer
FQDN="scscf.IMS_DOMAIN"
Realm="IMS_DOMAIN"
Vendor_Id="10415"
Product_Name="CDiameterPeer"
AcceptUnknownPeers="1"
DropUnknownOnDisconnect="1"
Tc="30"
Workers="16"
QueueLength="32"
TransactionTimeout="5"
SessionsHashSize="128"
DefaultAuthSessionTimeout="3600"
MaxAuthSessionTimeout="3600"
>
<Peer FQDN="hss.IMS_DOMAIN" Realm="IMS_DOMAIN" port="3868"/>
<Acceptor port="3870" bind="SCSCF_IP"/>
<Auth id="16777216" vendor="10415"/><!-- 3GPP Cx -->
<Auth id="16777216" vendor="4491"/><!-- CableLabs Cx -->
<Auth id="16777216" vendor="13019"/><!-- ETSI/TISPAN Cx -->
<Auth id="16777216" vendor="0"/><!-- ETSI/TISPAN Cx -->
<Auth id="4" vendor="10415"/> <!--3GPP Ro -->
<Acct id="4" vendor="10415" />
<!--
Supported Vendor IDs - list of values which will be sent in the CER/CEA in the
Supported-Vendor-ID AVPs
-->
<SupportedVendor vendor="10415" />
<DefaultRoute FQDN="hss.IMS_DOMAIN" metric="10"/>
</DiameterPeer>

View File

@@ -0,0 +1,112 @@
#!/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"
SCSCF_IP=${SCSCF_IP:-"$(host -4 $SCSCF_HOSTNAME |awk '/has.*address/{print $NF; exit}')"}
export SCSCF_IP
echo "SCSCF_IP: $SCSCF_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 "$SCSCF_IP" ]] \
|| [[ -z "$DNS_IP" ]]; then
echo "Unable to resolve some IPs... restarting"
exit 1
fi
IMS_DOMAIN=$IMS_DOMAIN
mkdir /etc/kamailio_scscf
cp /mnt/scscf/scscf.cfg /etc/kamailio_scscf
cp /mnt/scscf/scscf.xml /etc/kamailio_scscf
cp /mnt/scscf/kamailio_scscf.cfg /etc/kamailio_scscf
cp /mnt/scscf/CxDataType_Rel6.xsd /etc/kamailio_scscf
cp /mnt/scscf/CxDataType_Rel7.xsd /etc/kamailio_scscf
cp /mnt/scscf/CxDataType_Rel8.xsd /etc/kamailio_scscf
cp /mnt/scscf/dispatcher.list /etc/kamailio_scscf
while ! mysqladmin ping -h ${MYSQL_IP} --silent; do
sleep 5;
done
# Sleep until permissions are set
sleep 10;
# Create SCSCF database, populate tables and grant privileges
if [[ -z "`mysql -u root -h ${MYSQL_IP} -qfsBe "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='scscf'" 2>&1`" ]];
then
mysql -u root -h ${MYSQL_IP} -e "create database scscf;"
mysql -u root -h ${MYSQL_IP} scscf < /usr/local/src/kamailio/utils/kamctl/mysql/standard-create.sql
mysql -u root -h ${MYSQL_IP} scscf < /usr/local/src/kamailio/utils/kamctl/mysql/presence-create.sql
mysql -u root -h ${MYSQL_IP} scscf < /usr/local/src/kamailio/utils/kamctl/mysql/ims_usrloc_scscf-create.sql
mysql -u root -h ${MYSQL_IP} scscf < /usr/local/src/kamailio/utils/kamctl/mysql/ims_dialog-create.sql
mysql -u root -h ${MYSQL_IP} scscf < /usr/local/src/kamailio/utils/kamctl/mysql/ims_charging-create.sql
SCSCF_USER_EXISTS=`mysql -u root -h ${MYSQL_IP} -s -N -e "SELECT EXISTS(SELECT 1 FROM mysql.user WHERE User = 'scscf' AND Host = '%')"`
if [[ "$SCSCF_USER_EXISTS" == 0 ]]
then
mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'scscf'@'%' IDENTIFIED VIA mysql_native_password USING PASSWORD('heslo')";
mysql -u root -h ${MYSQL_IP} -e "CREATE USER 'scscf'@'$SCSCF_IP' IDENTIFIED VIA mysql_native_password USING PASSWORD('heslo')";
mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON scscf.* TO 'scscf'@'%'";
mysql -u root -h ${MYSQL_IP} -e "GRANT ALL ON scscf.* TO 'scscf'@'$SCSCF_IP'";
mysql -u root -h ${MYSQL_IP} -e "FLUSH PRIVILEGES;"
fi
fi
export IMS_SLASH_DOMAIN=`echo $IMS_DOMAIN | sed 's/\./\\\./g'`
sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' /etc/kamailio_scscf/scscf.cfg
sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/kamailio_scscf/scscf.cfg
sed -i 's|IMS_SLASH_DOMAIN|'$IMS_SLASH_DOMAIN'|g' /etc/kamailio_scscf/scscf.cfg
sed -i 's|MYSQL_IP|'$MYSQL_IP'|g' /etc/kamailio_scscf/scscf.cfg
sed -i 's|SCSCF_IP|'$SCSCF_IP'|g' /etc/kamailio_scscf/scscf.xml
sed -i 's|IMS_DOMAIN|'$IMS_DOMAIN'|g' /etc/kamailio_scscf/scscf.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

View File

@@ -0,0 +1,61 @@
# BSD 2-Clause License
# Copyright (c) 2020, Supreeth Herle
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
FROM ubuntu:focal
ENV DEBIAN_FRONTEND=noninteractive
ENV DEB_BUILD_PROFILES="pkg.ngcp-rtpengine.nobcg729"
# Install updates and dependencies
RUN apt-get update && \
apt-get -y install git vim tmux dpkg-dev debhelper libxtables-dev default-libmysqlclient-dev gperf libavcodec-dev libavfilter-dev libavformat-dev \
libavutil-dev libbencode-perl libcrypt-openssl-rsa-perl libcrypt-rijndael-perl libdigest-crc-perl libdigest-hmac-perl \
libevent-dev libhiredis-dev libio-multiplex-perl libio-socket-inet6-perl libiptc-dev libjson-glib-dev libnet-interface-perl \
libpcap0.8-dev libpcre3-dev libsocket6-perl libspandsp-dev libssl-dev libswresample-dev libsystemd-dev libxmlrpc-core-c3-dev \
markdown dkms module-assistant keyutils libnfsidmap2 nfs-common rpcbind libglib2.0-dev zlib1g-dev libavcodec-extra \
libcurl4-openssl-dev netcat-openbsd netcat iptables iproute2 net-tools iputils-ping libconfig-tiny-perl libwebsockets-dev dnsutils
# Fetch RTPEngine code (tag mr9.4.1.1), build and install
RUN git clone --depth 1 --branch mr9.4.1.1 https://github.com/sipwise/rtpengine && \
cd rtpengine && dpkg-checkbuilddeps && \
dpkg-buildpackage -b -uc -us && cd .. && \
dpkg -i *.deb && ldconfig
COPY rtpengine_init.sh /mnt/rtpengine/
RUN chmod +x /mnt/rtpengine/rtpengine_init.sh
ENV GW_HOSTNAME=upf \
RTPENGINE_HOSTNAME=rtpengine \
TABLE=0 \
PIDFILE=/run/ngcp-rtpengine-daemon.pid \
PORT_MAX=50000 \
PORT_MIN=49000 \
NO_FALLBACK=no \
TOS=184 \
APN_IMS_SUBNET=192.168.101.0/24
CMD /mnt/rtpengine/rtpengine_init.sh

View File

@@ -0,0 +1,3 @@
IMAGE_TAG=9.4.1.1
#comma separated list of platforms. If empty, image will not be multiarch.
PLATFORMS=linux/amd64

View File

@@ -0,0 +1,110 @@
#!/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.
set -x
RUNTIME=${1:-rtpengine}
if lsmod | grep xt_RTPENGINE || modprobe xt_RTPENGINE; then
echo "rtpengine kernel module already loaded."
else
modprobe xt_RTPENGINE
fi
GW_IP=${GW_IP:-"$(host -4 $GW_HOSTNAME |awk '/has.*address/{print $NF; exit}')"}
export GW_IP
echo "GW_IP: $GW_IP"
INTERFACE_IP=${INTERFACE_IP:-"$(host -4 $RTPENGINE_HOSTNAME |awk '/has.*address/{print $NF; exit}')"}
export INTERFACE_IP
echo "INTERFACE_IP: $INTERFACE_IP"
LISTEN_NG=${INTERFACE_IP}:2223
export LISTEN_NG
echo "LISTEN_NG: $LISTEN_NG"
if [ -z "$GW_IP" ]
then
echo "Unable to resolve some IPs... restarting"
exit 1
fi
# Populate options of the rtpengine cli command
[ -z "$INTERFACE_IP" ] && INTERFACE_IP="$(awk 'END{print $1}' /etc/hosts)"
[ -z "$TABLE" ] && TABLE="0"
[ -z "$LISTEN_NG" ] && LISTEN_NG="$(awk 'END{print $1}' /etc/hosts):2223"
[ -z "$PORT_MIN" ] && PORT_MIN="30000"
[ -z "$PORT_MAX" ] && PORT_MAX="40000"
[ -z "$TOS" ] && TOS="184"
[ -z "$PIDFILE" ] && PIDFILE="/run/ngcp-rtpengine-daemon.pid"
LISTEN_CLI="$(awk 'END{print $1}' /etc/hosts):9901"
OPTIONS=""
OPTIONS="$OPTIONS --interface=$INTERFACE_IP --listen-ng=$LISTEN_NG --listen-cli=$LISTEN_CLI --pidfile=$PIDFILE --port-min=$PORT_MIN --port-max=$PORT_MAX "
OPTIONS="$OPTIONS --table=$TABLE --tos=$TOS --foreground"
if test "$NO_FALLBACK" = "yes" ; then
OPTIONS="$OPTIONS --no-fallback"
fi
# Sync docker time
#ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
set +e
if [ -e /proc/rtpengine/control ]; then
echo "del $TABLE" > /proc/rtpengine/control 2>/dev/null
fi
# Freshly add the iptables rules to forward the udp packets to the iptables-extension "RTPEngine":
# Remember iptables table = chains, rules stored in the chains
# -N (create a new chain with the name rtpengine)
iptables -N rtpengine 2> /dev/null
# -D: Delete the rule for the target "rtpengine" if exists. -j (target): chain name or extension name
# from the table "filter" (the default -without the option '-t')
iptables -D INPUT -j rtpengine 2> /dev/null
# Add the rule again so the packets will go to rtpengine chain after the (filter-INPUT) hook point.
iptables -I INPUT -j rtpengine
# Delete and Insert a rule in the rtpengine chain to forward the UDP traffic
iptables -D rtpengine -p udp -j RTPENGINE --id "$TABLE" 2>/dev/null
iptables -I rtpengine -p udp -j RTPENGINE --id "$TABLE"
iptables-save > /etc/iptables.rules
# The same for IPv6
ip6tables -N rtpengine 2> /dev/null
ip6tables -D INPUT -j rtpengine 2> /dev/null
ip6tables -I INPUT -j rtpengine
ip6tables -D rtpengine -p udp -j RTPENGINE --id "$TABLE" 2>/dev/null
ip6tables -I rtpengine -p udp -j RTPENGINE --id "$TABLE"
ip6tables-save > /etc/ip6tables.rules
# Add static route to route traffic back to UE as there is not NATing
ip r add ${APN_IMS_SUBNET} via ${GW_IP}
set -x
exec $RUNTIME $OPTIONS