From 69247981c79e01c99b9db0e0edf97008f6819528 Mon Sep 17 00:00:00 2001 From: kevinnguyenai Date: Mon, 6 Sep 2021 11:10:22 +0700 Subject: [PATCH] dev asterisk env --- asterisk/.dockerignore | 7 + asterisk/.travis.yml | 6 + asterisk/docker-asterisk-0.9.9/.dockerignore | 7 + asterisk/docker-asterisk-0.9.9/.gitignore | 4 + asterisk/docker-asterisk-0.9.9/.gitmodules | 3 + asterisk/docker-asterisk-0.9.9/.travis.yml | 6 + asterisk/docker-asterisk-0.9.9/CHANGELOG.md | 180 ++ asterisk/docker-asterisk-0.9.9/Dockerfile | 176 ++ asterisk/docker-asterisk-0.9.9/LICENSE.txt | 21 + asterisk/docker-asterisk-0.9.9/Makefile | 79 + asterisk/docker-asterisk-0.9.9/README.md | 405 ++++ asterisk/docker-asterisk-0.9.9/ROADMAP.md | 31 + asterisk/docker-asterisk-0.9.9/demo/.env | 6 + .../docker-asterisk-0.9.9/demo/.gitignore | 1 + asterisk/docker-asterisk-0.9.9/demo/Makefile | 166 ++ .../demo/docker-compose.yml | 29 + asterisk/docker-asterisk-0.9.9/hooks/build | 24 + .../docker-asterisk-0.9.9/hooks/pre_build | 17 + .../src/acme/bin/acme-extract.sh | 193 ++ .../src/acme/entry.d/10-acme-common | 58 + .../src/acme/entry.d/50-acme-monitor-tlscert | 13 + .../src/asterisk/config/alsa.conf | 2 + .../src/asterisk/config/asterisk.conf | 22 + .../src/asterisk/config/ccss.conf | 0 .../src/asterisk/config/cli_aliases.conf | 16 + .../src/asterisk/config/features.conf | 0 .../src/asterisk/config/indications.conf | 737 ++++++ .../src/asterisk/config/logger.conf | 8 + .../src/asterisk/config/modules.conf | 74 + .../src/asterisk/config/musiconhold.conf | 6 + .../src/asterisk/config/pjproject.conf | 3 + .../src/asterisk/config/rtp.conf | 11 + .../asterisk/entry.d/50-asterisk-seed-conf | 19 + .../entry.d/51-asterisk-generate-tlscert | 18 + .../src/autoban/README.md | 1 + .../src/autoban/bin/autoban | 1 + .../src/autoban/config/autoban.conf | 20 + .../src/autoban/config/manager.conf | 9 + .../src/autoban/doc/autoban.conf.sample | 28 + .../src/autoban/doc/autoban.md | 146 ++ .../autoban/entry.d/50-autoban-read-nftfile | 48 + .../autoban/exit.d/50-autoban-write-nftfile | 29 + .../src/autoban/nft/autoban.nft | 30 + .../src/autoban/php/autoban.class.inc | 226 ++ .../src/autoban/php/autoban.php | 177 ++ .../src/autoban/php/autoband.php | 77 + .../src/autoban/php/nft.class.inc | 327 +++ .../src/common/php/error.inc | 36 + .../src/docker/bin/docker-common.sh | 146 ++ .../src/docker/bin/docker-config.sh | 280 +++ .../src/docker/bin/docker-entrypoint.sh | 84 + .../src/docker/bin/docker-service.sh | 120 + .../docker/entry.d/20-docker-print-versions | 5 + .../docker/entry.d/50-docker-update-loglevel | 7 + .../src/notused/bin/astqueue.sh | 32 + .../src/notused/bin/relpath | 21 + .../src/notused/bin/voipbl.sh | 8 + .../src/notused/entry.d/20-cronjob-voipbl | 46 + .../src/notused/php/amiupdateconfig.class.inc | 70 + .../src/privatedial/README.md | 1 + .../src/privatedial/bin/minivm-send | 69 + .../src/privatedial/config/extensions.conf | 351 +++ .../privatedial/config/extensions_local.conf | 34 + .../src/privatedial/config/minivm.conf | 36 + .../src/privatedial/config/pjsip.conf | 15 + .../privatedial/config/pjsip_endpoint.conf | 36 + .../privatedial/config/pjsip_transport.conf | 29 + .../src/privatedial/config/pjsip_wizard.conf | 67 + .../src/privatedial/doc/privatedial.md | 242 ++ .../src/websms/README.md | 1 + .../src/websms/config/websms.conf | 22 + .../src/websms/doc/websms.conf.sample | 47 + .../src/websms/doc/websms.md | 342 +++ .../src/websms/entry.d/50-websms-update-port | 15 + .../src/websms/php/astqueue.class.inc | 261 ++ .../src/websms/php/websms.class.inc | 599 +++++ .../src/websms/php/websms.php | 28 + .../src/websms/php/websmsd.php | 34 + .../sub/module/phpami/.gitignore | 5 + .../sub/module/phpami/LICENSE | 458 ++++ .../sub/module/phpami/README.md | 58 + .../sub/module/phpami/composer.json | 54 + .../sub/module/phpami/composer.lock | 126 + .../sub/module/phpami/phpcs.xml | 12 + .../module/phpami/phpcs/PHPAMI/ruleset.xml | 7 + .../sub/module/phpami/src/Ami.php | 1249 ++++++++++ asterisk/docker-asterisk-0.9.9/test/Makefile | 159 ++ .../test/acme/.gitignore | 4 + asterisk/docker-asterisk-0.9.9/test/dkr.mk | 34 + asterisk/docker-asterisk-0.9.9/test/ssl.mk | 125 + .../docker-asterisk-0.9.9/test/ssl/.gitignore | 4 + docker-compose.yml | 10 +- kamailio/Dockerfile | 4 +- kamailio/dispatcher.list | 90 +- kamailio/dispatcher.list.001 | 46 + kamailio/kamailio.cfg | 1411 +++-------- kamailio/kamailio.cfg.001 | 1128 +++++++++ kamailio/kamailio.cfg.002 | 1124 +++++++++ kamailio/kamailio.cfg.bak | 2108 ++++++++--------- kamailio/kamctlrc | 162 ++ mount/asterisk/conf/acl.conf | 80 + mount/asterisk/conf/adsi.conf | 8 + mount/asterisk/conf/agents.conf | 70 + mount/asterisk/conf/alarmreceiver.conf | 91 + mount/asterisk/conf/alsa.conf | 77 + mount/asterisk/conf/amd.conf | 27 + mount/asterisk/conf/app_mysql.conf | 24 + mount/asterisk/conf/app_skel.conf | 27 + mount/asterisk/conf/ari.conf | 37 + mount/asterisk/conf/ast_debug_tools.conf | 63 + mount/asterisk/conf/asterisk.adsi | 158 ++ mount/asterisk/conf/asterisk.conf | 133 ++ mount/asterisk/conf/calendar.conf | 111 + mount/asterisk/conf/ccss.conf | 205 ++ mount/asterisk/conf/cdr.conf | 166 ++ mount/asterisk/conf/cdr_adaptive_odbc.conf | 62 + mount/asterisk/conf/cdr_beanstalkd.conf | 20 + mount/asterisk/conf/cdr_custom.conf | 14 + mount/asterisk/conf/cdr_manager.conf | 15 + mount/asterisk/conf/cdr_mysql.conf | 62 + mount/asterisk/conf/cdr_odbc.conf | 12 + mount/asterisk/conf/cdr_pgsql.conf | 16 + mount/asterisk/conf/cdr_sqlite3_custom.conf | 11 + mount/asterisk/conf/cdr_syslog.conf | 83 + mount/asterisk/conf/cdr_tds.conf | 77 + mount/asterisk/conf/cel.conf | 116 + mount/asterisk/conf/cel_beanstalkd.conf | 21 + mount/asterisk/conf/cel_custom.conf | 35 + mount/asterisk/conf/cel_odbc.conf | 108 + mount/asterisk/conf/cel_pgsql.conf | 73 + mount/asterisk/conf/cel_sqlite3_custom.conf | 25 + mount/asterisk/conf/cel_tds.conf | 69 + mount/asterisk/conf/chan_dahdi.conf | 1717 ++++++++++++++ mount/asterisk/conf/chan_mobile.conf | 69 + mount/asterisk/conf/cli.conf | 12 + mount/asterisk/conf/cli_aliases.conf | 203 ++ mount/asterisk/conf/cli_permissions.conf | 82 + mount/asterisk/conf/codecs.conf | 214 ++ mount/asterisk/conf/confbridge.conf | 450 ++++ mount/asterisk/conf/config_test.conf | 46 + mount/asterisk/conf/console.conf | 97 + mount/asterisk/conf/dbsep.conf | 34 + mount/asterisk/conf/dnsmgr.conf | 5 + mount/asterisk/conf/dsp.conf | 42 + mount/asterisk/conf/dundi.conf | 277 +++ mount/asterisk/conf/enum.conf | 22 + mount/asterisk/conf/extconfig.conf | 112 + mount/asterisk/conf/extensions.ael | 456 ++++ mount/asterisk/conf/extensions.conf | 862 +++++++ mount/asterisk/conf/extensions.lua | 240 ++ mount/asterisk/conf/extensions_minivm.conf | 156 ++ mount/asterisk/conf/features.conf | 122 + mount/asterisk/conf/festival.conf | 34 + mount/asterisk/conf/followme.conf | 107 + mount/asterisk/conf/func_odbc.conf | 112 + mount/asterisk/conf/hep.conf | 32 + mount/asterisk/conf/http.conf | 132 ++ mount/asterisk/conf/iax.conf | 669 ++++++ mount/asterisk/conf/iaxprov.conf | 80 + mount/asterisk/conf/indications.conf | 747 ++++++ mount/asterisk/conf/logger.conf | 173 ++ mount/asterisk/conf/manager.conf | 158 ++ mount/asterisk/conf/meetme.conf | 45 + mount/asterisk/conf/mgcp.conf | 142 ++ mount/asterisk/conf/minivm.conf | 218 ++ mount/asterisk/conf/misdn.conf | 537 +++++ mount/asterisk/conf/modules.conf | 53 + mount/asterisk/conf/motif.conf | 99 + mount/asterisk/conf/musiconhold.conf | 145 ++ mount/asterisk/conf/muted.conf | 39 + mount/asterisk/conf/ooh323.conf | 203 ++ mount/asterisk/conf/osp.conf | 117 + mount/asterisk/conf/oss.conf | 152 ++ mount/asterisk/conf/phone.conf | 51 + mount/asterisk/conf/phoneprov.conf | 142 ++ mount/asterisk/conf/pjproject.conf | 56 + mount/asterisk/conf/pjsip.conf | 1467 ++++++++++++ mount/asterisk/conf/pjsip_notify.conf | 57 + mount/asterisk/conf/pjsip_wizard.conf | 163 ++ mount/asterisk/conf/prometheus.conf | 58 + mount/asterisk/conf/queuerules.conf | 47 + mount/asterisk/conf/queues.conf | 562 +++++ mount/asterisk/conf/res_config_mysql.conf | 43 + mount/asterisk/conf/res_config_sqlite.conf | 11 + mount/asterisk/conf/res_config_sqlite3.conf | 35 + mount/asterisk/conf/res_corosync.conf | 31 + mount/asterisk/conf/res_curl.conf | 9 + mount/asterisk/conf/res_fax.conf | 32 + mount/asterisk/conf/res_ldap.conf | 198 ++ mount/asterisk/conf/res_odbc.conf | 125 + mount/asterisk/conf/res_parking.conf | 163 ++ mount/asterisk/conf/res_pgsql.conf | 30 + mount/asterisk/conf/res_pktccops.conf | 32 + mount/asterisk/conf/res_snmp.conf | 22 + mount/asterisk/conf/res_stun_monitor.conf | 27 + mount/asterisk/conf/resolver_unbound.conf | 23 + mount/asterisk/conf/rtp.conf | 144 ++ mount/asterisk/conf/say.conf | 383 +++ mount/asterisk/conf/sip.conf | 1621 +++++++++++++ mount/asterisk/conf/sip_notify.conf | 57 + mount/asterisk/conf/skinny.conf | 207 ++ mount/asterisk/conf/sla.conf | 150 ++ mount/asterisk/conf/smdi.conf | 75 + mount/asterisk/conf/sorcery.conf | 78 + mount/asterisk/conf/ss7.timers | 65 + mount/asterisk/conf/stasis.conf | 132 ++ mount/asterisk/conf/statsd.conf | 8 + mount/asterisk/conf/stir_shaken.conf | 61 + mount/asterisk/conf/telcordia-1.adsi | 83 + mount/asterisk/conf/test_sorcery.conf | 14 + mount/asterisk/conf/udptl.conf | 26 + mount/asterisk/conf/unistim.conf | 88 + mount/asterisk/conf/users.conf | 113 + mount/asterisk/conf/voicemail.conf | 500 ++++ mount/asterisk/conf/vpb.conf | 248 ++ mount/asterisk/conf/xmpp.conf | 64 + 216 files changed, 31526 insertions(+), 2212 deletions(-) create mode 100644 asterisk/.dockerignore create mode 100644 asterisk/.travis.yml create mode 100644 asterisk/docker-asterisk-0.9.9/.dockerignore create mode 100644 asterisk/docker-asterisk-0.9.9/.gitignore create mode 100644 asterisk/docker-asterisk-0.9.9/.gitmodules create mode 100644 asterisk/docker-asterisk-0.9.9/.travis.yml create mode 100644 asterisk/docker-asterisk-0.9.9/CHANGELOG.md create mode 100644 asterisk/docker-asterisk-0.9.9/Dockerfile create mode 100644 asterisk/docker-asterisk-0.9.9/LICENSE.txt create mode 100644 asterisk/docker-asterisk-0.9.9/Makefile create mode 100644 asterisk/docker-asterisk-0.9.9/README.md create mode 100644 asterisk/docker-asterisk-0.9.9/ROADMAP.md create mode 100644 asterisk/docker-asterisk-0.9.9/demo/.env create mode 100644 asterisk/docker-asterisk-0.9.9/demo/.gitignore create mode 100644 asterisk/docker-asterisk-0.9.9/demo/Makefile create mode 100644 asterisk/docker-asterisk-0.9.9/demo/docker-compose.yml create mode 100644 asterisk/docker-asterisk-0.9.9/hooks/build create mode 100644 asterisk/docker-asterisk-0.9.9/hooks/pre_build create mode 100755 asterisk/docker-asterisk-0.9.9/src/acme/bin/acme-extract.sh create mode 100755 asterisk/docker-asterisk-0.9.9/src/acme/entry.d/10-acme-common create mode 100755 asterisk/docker-asterisk-0.9.9/src/acme/entry.d/50-acme-monitor-tlscert create mode 100644 asterisk/docker-asterisk-0.9.9/src/asterisk/config/alsa.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/asterisk/config/asterisk.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/asterisk/config/ccss.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/asterisk/config/cli_aliases.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/asterisk/config/features.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/asterisk/config/indications.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/asterisk/config/logger.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/asterisk/config/modules.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/asterisk/config/musiconhold.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/asterisk/config/pjproject.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/asterisk/config/rtp.conf create mode 100755 asterisk/docker-asterisk-0.9.9/src/asterisk/entry.d/50-asterisk-seed-conf create mode 100755 asterisk/docker-asterisk-0.9.9/src/asterisk/entry.d/51-asterisk-generate-tlscert create mode 120000 asterisk/docker-asterisk-0.9.9/src/autoban/README.md create mode 120000 asterisk/docker-asterisk-0.9.9/src/autoban/bin/autoban create mode 100644 asterisk/docker-asterisk-0.9.9/src/autoban/config/autoban.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/autoban/config/manager.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/autoban/doc/autoban.conf.sample create mode 100644 asterisk/docker-asterisk-0.9.9/src/autoban/doc/autoban.md create mode 100755 asterisk/docker-asterisk-0.9.9/src/autoban/entry.d/50-autoban-read-nftfile create mode 100755 asterisk/docker-asterisk-0.9.9/src/autoban/exit.d/50-autoban-write-nftfile create mode 100644 asterisk/docker-asterisk-0.9.9/src/autoban/nft/autoban.nft create mode 100644 asterisk/docker-asterisk-0.9.9/src/autoban/php/autoban.class.inc create mode 100755 asterisk/docker-asterisk-0.9.9/src/autoban/php/autoban.php create mode 100755 asterisk/docker-asterisk-0.9.9/src/autoban/php/autoband.php create mode 100644 asterisk/docker-asterisk-0.9.9/src/autoban/php/nft.class.inc create mode 100644 asterisk/docker-asterisk-0.9.9/src/common/php/error.inc create mode 100644 asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-common.sh create mode 100644 asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-config.sh create mode 100755 asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-entrypoint.sh create mode 100755 asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-service.sh create mode 100755 asterisk/docker-asterisk-0.9.9/src/docker/entry.d/20-docker-print-versions create mode 100755 asterisk/docker-asterisk-0.9.9/src/docker/entry.d/50-docker-update-loglevel create mode 100755 asterisk/docker-asterisk-0.9.9/src/notused/bin/astqueue.sh create mode 100755 asterisk/docker-asterisk-0.9.9/src/notused/bin/relpath create mode 100755 asterisk/docker-asterisk-0.9.9/src/notused/bin/voipbl.sh create mode 100644 asterisk/docker-asterisk-0.9.9/src/notused/entry.d/20-cronjob-voipbl create mode 100644 asterisk/docker-asterisk-0.9.9/src/notused/php/amiupdateconfig.class.inc create mode 120000 asterisk/docker-asterisk-0.9.9/src/privatedial/README.md create mode 100755 asterisk/docker-asterisk-0.9.9/src/privatedial/bin/minivm-send create mode 100644 asterisk/docker-asterisk-0.9.9/src/privatedial/config/extensions.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/privatedial/config/extensions_local.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/privatedial/config/minivm.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip_endpoint.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip_transport.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip_wizard.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/privatedial/doc/privatedial.md create mode 120000 asterisk/docker-asterisk-0.9.9/src/websms/README.md create mode 100644 asterisk/docker-asterisk-0.9.9/src/websms/config/websms.conf create mode 100644 asterisk/docker-asterisk-0.9.9/src/websms/doc/websms.conf.sample create mode 100644 asterisk/docker-asterisk-0.9.9/src/websms/doc/websms.md create mode 100755 asterisk/docker-asterisk-0.9.9/src/websms/entry.d/50-websms-update-port create mode 100644 asterisk/docker-asterisk-0.9.9/src/websms/php/astqueue.class.inc create mode 100644 asterisk/docker-asterisk-0.9.9/src/websms/php/websms.class.inc create mode 100755 asterisk/docker-asterisk-0.9.9/src/websms/php/websms.php create mode 100644 asterisk/docker-asterisk-0.9.9/src/websms/php/websmsd.php create mode 100644 asterisk/docker-asterisk-0.9.9/sub/module/phpami/.gitignore create mode 100644 asterisk/docker-asterisk-0.9.9/sub/module/phpami/LICENSE create mode 100644 asterisk/docker-asterisk-0.9.9/sub/module/phpami/README.md create mode 100644 asterisk/docker-asterisk-0.9.9/sub/module/phpami/composer.json create mode 100644 asterisk/docker-asterisk-0.9.9/sub/module/phpami/composer.lock create mode 100644 asterisk/docker-asterisk-0.9.9/sub/module/phpami/phpcs.xml create mode 100644 asterisk/docker-asterisk-0.9.9/sub/module/phpami/phpcs/PHPAMI/ruleset.xml create mode 100644 asterisk/docker-asterisk-0.9.9/sub/module/phpami/src/Ami.php create mode 100644 asterisk/docker-asterisk-0.9.9/test/Makefile create mode 100644 asterisk/docker-asterisk-0.9.9/test/acme/.gitignore create mode 100644 asterisk/docker-asterisk-0.9.9/test/dkr.mk create mode 100644 asterisk/docker-asterisk-0.9.9/test/ssl.mk create mode 100644 asterisk/docker-asterisk-0.9.9/test/ssl/.gitignore create mode 100644 kamailio/dispatcher.list.001 create mode 100644 kamailio/kamailio.cfg.001 create mode 100644 kamailio/kamailio.cfg.002 create mode 100644 kamailio/kamctlrc create mode 100644 mount/asterisk/conf/acl.conf create mode 100644 mount/asterisk/conf/adsi.conf create mode 100644 mount/asterisk/conf/agents.conf create mode 100644 mount/asterisk/conf/alarmreceiver.conf create mode 100644 mount/asterisk/conf/alsa.conf create mode 100644 mount/asterisk/conf/amd.conf create mode 100644 mount/asterisk/conf/app_mysql.conf create mode 100644 mount/asterisk/conf/app_skel.conf create mode 100644 mount/asterisk/conf/ari.conf create mode 100644 mount/asterisk/conf/ast_debug_tools.conf create mode 100644 mount/asterisk/conf/asterisk.adsi create mode 100644 mount/asterisk/conf/asterisk.conf create mode 100644 mount/asterisk/conf/calendar.conf create mode 100644 mount/asterisk/conf/ccss.conf create mode 100644 mount/asterisk/conf/cdr.conf create mode 100644 mount/asterisk/conf/cdr_adaptive_odbc.conf create mode 100644 mount/asterisk/conf/cdr_beanstalkd.conf create mode 100644 mount/asterisk/conf/cdr_custom.conf create mode 100644 mount/asterisk/conf/cdr_manager.conf create mode 100644 mount/asterisk/conf/cdr_mysql.conf create mode 100644 mount/asterisk/conf/cdr_odbc.conf create mode 100644 mount/asterisk/conf/cdr_pgsql.conf create mode 100644 mount/asterisk/conf/cdr_sqlite3_custom.conf create mode 100644 mount/asterisk/conf/cdr_syslog.conf create mode 100644 mount/asterisk/conf/cdr_tds.conf create mode 100644 mount/asterisk/conf/cel.conf create mode 100644 mount/asterisk/conf/cel_beanstalkd.conf create mode 100644 mount/asterisk/conf/cel_custom.conf create mode 100644 mount/asterisk/conf/cel_odbc.conf create mode 100644 mount/asterisk/conf/cel_pgsql.conf create mode 100644 mount/asterisk/conf/cel_sqlite3_custom.conf create mode 100644 mount/asterisk/conf/cel_tds.conf create mode 100644 mount/asterisk/conf/chan_dahdi.conf create mode 100644 mount/asterisk/conf/chan_mobile.conf create mode 100644 mount/asterisk/conf/cli.conf create mode 100644 mount/asterisk/conf/cli_aliases.conf create mode 100644 mount/asterisk/conf/cli_permissions.conf create mode 100644 mount/asterisk/conf/codecs.conf create mode 100644 mount/asterisk/conf/confbridge.conf create mode 100644 mount/asterisk/conf/config_test.conf create mode 100644 mount/asterisk/conf/console.conf create mode 100644 mount/asterisk/conf/dbsep.conf create mode 100644 mount/asterisk/conf/dnsmgr.conf create mode 100644 mount/asterisk/conf/dsp.conf create mode 100644 mount/asterisk/conf/dundi.conf create mode 100644 mount/asterisk/conf/enum.conf create mode 100644 mount/asterisk/conf/extconfig.conf create mode 100644 mount/asterisk/conf/extensions.ael create mode 100644 mount/asterisk/conf/extensions.conf create mode 100644 mount/asterisk/conf/extensions.lua create mode 100644 mount/asterisk/conf/extensions_minivm.conf create mode 100644 mount/asterisk/conf/features.conf create mode 100644 mount/asterisk/conf/festival.conf create mode 100644 mount/asterisk/conf/followme.conf create mode 100644 mount/asterisk/conf/func_odbc.conf create mode 100644 mount/asterisk/conf/hep.conf create mode 100644 mount/asterisk/conf/http.conf create mode 100644 mount/asterisk/conf/iax.conf create mode 100644 mount/asterisk/conf/iaxprov.conf create mode 100644 mount/asterisk/conf/indications.conf create mode 100644 mount/asterisk/conf/logger.conf create mode 100644 mount/asterisk/conf/manager.conf create mode 100644 mount/asterisk/conf/meetme.conf create mode 100644 mount/asterisk/conf/mgcp.conf create mode 100644 mount/asterisk/conf/minivm.conf create mode 100644 mount/asterisk/conf/misdn.conf create mode 100644 mount/asterisk/conf/modules.conf create mode 100644 mount/asterisk/conf/motif.conf create mode 100644 mount/asterisk/conf/musiconhold.conf create mode 100644 mount/asterisk/conf/muted.conf create mode 100644 mount/asterisk/conf/ooh323.conf create mode 100644 mount/asterisk/conf/osp.conf create mode 100644 mount/asterisk/conf/oss.conf create mode 100644 mount/asterisk/conf/phone.conf create mode 100644 mount/asterisk/conf/phoneprov.conf create mode 100644 mount/asterisk/conf/pjproject.conf create mode 100644 mount/asterisk/conf/pjsip.conf create mode 100644 mount/asterisk/conf/pjsip_notify.conf create mode 100644 mount/asterisk/conf/pjsip_wizard.conf create mode 100644 mount/asterisk/conf/prometheus.conf create mode 100644 mount/asterisk/conf/queuerules.conf create mode 100644 mount/asterisk/conf/queues.conf create mode 100644 mount/asterisk/conf/res_config_mysql.conf create mode 100644 mount/asterisk/conf/res_config_sqlite.conf create mode 100644 mount/asterisk/conf/res_config_sqlite3.conf create mode 100644 mount/asterisk/conf/res_corosync.conf create mode 100644 mount/asterisk/conf/res_curl.conf create mode 100644 mount/asterisk/conf/res_fax.conf create mode 100644 mount/asterisk/conf/res_ldap.conf create mode 100644 mount/asterisk/conf/res_odbc.conf create mode 100644 mount/asterisk/conf/res_parking.conf create mode 100644 mount/asterisk/conf/res_pgsql.conf create mode 100644 mount/asterisk/conf/res_pktccops.conf create mode 100644 mount/asterisk/conf/res_snmp.conf create mode 100644 mount/asterisk/conf/res_stun_monitor.conf create mode 100644 mount/asterisk/conf/resolver_unbound.conf create mode 100644 mount/asterisk/conf/rtp.conf create mode 100644 mount/asterisk/conf/say.conf create mode 100644 mount/asterisk/conf/sip.conf create mode 100644 mount/asterisk/conf/sip_notify.conf create mode 100644 mount/asterisk/conf/skinny.conf create mode 100644 mount/asterisk/conf/sla.conf create mode 100644 mount/asterisk/conf/smdi.conf create mode 100644 mount/asterisk/conf/sorcery.conf create mode 100644 mount/asterisk/conf/ss7.timers create mode 100644 mount/asterisk/conf/stasis.conf create mode 100644 mount/asterisk/conf/statsd.conf create mode 100644 mount/asterisk/conf/stir_shaken.conf create mode 100644 mount/asterisk/conf/telcordia-1.adsi create mode 100644 mount/asterisk/conf/test_sorcery.conf create mode 100644 mount/asterisk/conf/udptl.conf create mode 100644 mount/asterisk/conf/unistim.conf create mode 100644 mount/asterisk/conf/users.conf create mode 100644 mount/asterisk/conf/voicemail.conf create mode 100644 mount/asterisk/conf/vpb.conf create mode 100644 mount/asterisk/conf/xmpp.conf diff --git a/asterisk/.dockerignore b/asterisk/.dockerignore new file mode 100644 index 0000000..e060d87 --- /dev/null +++ b/asterisk/.dockerignore @@ -0,0 +1,7 @@ +.git +.gitignore +.github +.gitattributes +src/notused +local +demo/ diff --git a/asterisk/.travis.yml b/asterisk/.travis.yml new file mode 100644 index 0000000..fa10cdf --- /dev/null +++ b/asterisk/.travis.yml @@ -0,0 +1,6 @@ +language: ruby +os: linux +dist: bionic +services: docker +install: make build-all +script: make test-all diff --git a/asterisk/docker-asterisk-0.9.9/.dockerignore b/asterisk/docker-asterisk-0.9.9/.dockerignore new file mode 100644 index 0000000..e060d87 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/.dockerignore @@ -0,0 +1,7 @@ +.git +.gitignore +.github +.gitattributes +src/notused +local +demo/ diff --git a/asterisk/docker-asterisk-0.9.9/.gitignore b/asterisk/docker-asterisk-0.9.9/.gitignore new file mode 100644 index 0000000..8d57883 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/.gitignore @@ -0,0 +1,4 @@ +*private +local* +sub/* +!sub/module diff --git a/asterisk/docker-asterisk-0.9.9/.gitmodules b/asterisk/docker-asterisk-0.9.9/.gitmodules new file mode 100644 index 0000000..484e8f8 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/.gitmodules @@ -0,0 +1,3 @@ +[submodule "sub/module/phpami"] + path = sub/module/phpami + url = https://github.com/ofbeaton/phpami.git diff --git a/asterisk/docker-asterisk-0.9.9/.travis.yml b/asterisk/docker-asterisk-0.9.9/.travis.yml new file mode 100644 index 0000000..fa10cdf --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/.travis.yml @@ -0,0 +1,6 @@ +language: ruby +os: linux +dist: bionic +services: docker +install: make build-all +script: make test-all diff --git a/asterisk/docker-asterisk-0.9.9/CHANGELOG.md b/asterisk/docker-asterisk-0.9.9/CHANGELOG.md new file mode 100644 index 0000000..ca5b741 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/CHANGELOG.md @@ -0,0 +1,180 @@ +# 0.9.9 + +- [docker](src/docker) Now use alpine:3.14 (asterisk:18.2.2). +- [docker](ROADMAP.md) Use [travis-ci.com](https://travis-ci.com/). + +# 0.9.8 + +- [autoban](src/autoban) Let autoband handle AMI connection failures nicely. + +# 0.9.7 + +- [docker](src/docker) Now use alpine:3.13 (asterisk:18.1.1). +- [test](test/Makefile) Move tests into test dir. + +# 0.9.6 + +- [repo](hooks) Fixed bug in hooks/pre_build. Use curl in `make pre_build`. + +# 0.9.5 + +- [codec](sub/codec) Provide the [G.729](https://en.wikipedia.org/wiki/G.729) and [G.723.1](https://en.wikipedia.org/wiki/G.723.1) audio codecs. +- [codec](sub/codec) Improved handling of codec versions (`BLD_CVER` in Makefile). + +# 0.9.4 + +- [websms](src/websms) Use `prox_addr = 172.16.0.0/12,192.168.0.0/16` by default. + +# 0.9.3 + +- [acme](src/acme) Introduce `ACME_POSTHOOK="sv restart asterisk"` and run that after we have updated the certificates. +- [docker](src/docker) Don't move `DOCKER_APPL_SSL_DIR=$DOCKER_SSL_DIR/asterisk` to persistent storage. Data there is updated at container startup anyway. Moreover there is no need to remove old data when it is updated. +- [privatedial](src/privatedial) In `pjsip_transport.conf` set `method=tlsv1_2` to harden TLS. + +# 0.9.2 + +- [docker](src/docker) Use the native envvar `SVDIR` instead of `DOCKER_RUNSV_DIR`. +- [docker](src/docker) Update docker-common.sh. +- [docker](src/docker) Now use docker-config.sh. +- [docker](src/docker) Update docker-entrypoint.sh. +- [docker](src/docker) Update docker-service.sh. +- [docker](src/docker) Now use DOCKER_ENTRY_DIR=/etc/docker/entry.d and DOCKER_EXIT_DIR=/etc/docker/exit.d. +- [docker](Makefile) Improved smoke test. +- [acme](src/acme/bin/acme-extract.sh) Update module. +- [privatedial](src/privatedial) Breaking change. Now use `cert_file=/etc/ssl/asterisk/cert.pem` and `priv_key_file=/etc/ssl/asterisk/priv_key.pem` + +# 0.9.1 + +- [repo](hooks) Added hooks/pre_build which assembles files from sub-modules. +- [repo](.travis.yml) Revisited `.travis.yml`. +- [docker](README.md) Proofread documentation. +- [docker](README.md) Fixed broken hyperlinks in documentation. + +# 0.9.0 + +- [privatedial](src/privatedial) Break out endpoints from pjsip_wizard.conf to pjsip_endpoint.conf. +- [privatedial](src/privatedial) Use Hangup() instead of Goto() when entering extension `h`. +- [privatedial](src/privatedial) Work around bug in [MinivmGreet()](https://wiki.asterisk.org/wiki/display/AST/Asterisk+16+Application_MinivmGreet). +- [privatedial](src/privatedial) Renamed dialplan contexts. +- [privatedial](src/privatedial) Dialplan `[sub_voicemail]` now handles CHANUNAVAIL correctly. +- [privatedial](src/privatedial) Added `endpoint/bind_rtp_to_media_address = yes` +- [docker](README.md) Complete documentation. +- [docker](src/docker) Now use alpine:3.12 (asterisk:16.7.0). +- [websms](src/websms) `WEBSMSD_PORT=80` sets PHP web server port, used by WebSMS. +- [repo](src) Harmonized file names in `entry.d` and `exit.d`. +- [repo](sub) Use git submodule for third party projects. + +# 0.8.0 + +- [websms](src/websms) Harmonized configuration parameter names. +- [websms](src/websms) Harmonized function names. +- [websms](src/websms) Facilitate static key-value pairs, `val_static = "key1=value1,key2=value2"`. +- [websms](src/websms) Parameter `val_numform`, now takes `E.164` (omit +) and `E.123`. +- [websms](src/websms) Improved Unicode configuration, allowing `val_unicode = "key=value"`. +- [websms](src/websms) Added authorization methods, `plain` and `none`. +- [websms](src/websms) Allow multiple API interfaces to be configured. +- [websms](src/websms) Now accept incoming message with null body. +- [websms](src/websms) Code clean up. +- [privatedial](src/privatedial) Use set_var=TRUNK_ENDPOINT to set outgoing target for each endpoint individually. +- [privatedial](src/privatedial) Don't use `endpoint/from_user`, it overwrites CallerID. + +# 0.7.0 + +- [acme](src/acme/bin/acme-extract.sh) Support both v1 and v2 formats of the acme.json file. +- [acme](src/acme/entry.d/50-acme-monitor-tlscert) Support both host and domain wildcard TLS certificates. +- [websms](src/websms) Complete documentation. +- [privatedial](src/privatedial) Advancing documentation. +- [docker](README.md) Advancing documentation. +- [docker](src/notused) Cleanup `src/notused`. +- [docker](src/docker) Consolidate common functions in src/docker/bin/docker-common.sh. + +# 0.6.0 + +- [docker](Dockerfile) Audio via PulseAudio. +- [docker](src/docker) Now use alpine:3.11 (asterisk:16.6.2). +- [demo](demo) Added demo. +- [demo](demo) Enabled audio via PulseAudio socket and cookie. +- [demo](demo) Use host timezone by mounting /etc/localtime. +- [websms](src/websms) Updating documentation. +- [privatedial](src/privatedial) Added demo-echotest in IVR. +- [privatedial](src/privatedial) Fixed initiation issue for minivm. + +# 0.5.2 + +- [websms](src/websms) Fixing bugs related to special characters in SMS messages +- [websms](src/websms) Added `val_unicode` parameter. Set to `ucs-2` to make sure all characters are within the Unicode BMP (up to U+FFFF). +- [websms](src/websms) Updating documentation. +- [websms](src/websms) Refactoring of `astqueue.class.ini` to better cope with message encoding. +- [privatedial](src/privatedial) added `sub_decode_body` to cope with encoded messages. + +# 0.5.1 + +- [docker](Makefile) Enable PHP profiling using xdebug. +- [autoban](src/autoban) Optimized code with respect to efficiency and speed. +- [autoban](src/autoban) Improved command line options of the shell utility. + +# 0.5.0 + +- [acme](src/acme) Fixed dumpcert.sh leaking to stdout. Have it write to logger instead. +- [autoban](src/autoban) Added shell utility autoban, which helps to manage the NFT state +- [autoban](src/autoban) Updated documentation. +- [autoban](src/autoban) Now write to autoban.nft every time we get a security event and update NFT, so that its state is always preserved. +- [autoban](src/autoban) Code base now refactored and split into autoban.class.inc and nft.class.inc +- [websms](src/websms) Updated documentation. + +# 0.4.0 + +- [privatedial](src/privatedial) Now keep main dial-plan conf files separate. +- [privatedial](src/privatedial) Start to document the PrivateDial dial-plan. +- [autoban](src/autoban) Now don't crash if autoban.conf does not have both an `[autoban]` and an `[nftables]` section. +- [autoban](src/autoban) Renamed autoband.php (it was autoban.php) +- [autoban](src/autoban) Updated documentation. +- [asterisk](src/asterisk) Added Networking section in README.md. + +# 0.3.0 + +- [acme](src/acme) New support for [Let’s Encrypt](https://letsencrypt.org/) LTS certificates using [Traefik](https://traefik.io/) using `ACME_FILE=/acme/acme.json`. +- [asterisk](src/asterisk) Configuration now supports UDP, TCP and TLS and SDES. +- [asterisk](src/asterisk) Generate self-signed TLS certificate. +- [asterisk](src/asterisk) Improved structure of `pjsip_wizard.conf`. +- [asterisk](src/asterisk) Don't answer when device is UNAVAILABLE in `[dp_answer]` +- [docker](src/docker) The [docker-service.sh](src/docker/bin/docker-service.sh) script now have options: down, force, log, name, source, quiet. +- [websms](src/websms) Added `val_numform` parameter. Set to `E164` to strip phone numbers from leading +. + +# 0.2.1 + +- [asterisk](src/asterisk) Sanitize incoming extensions so they are all international +- [asterisk](src/asterisk) Move APP_SMS global to extensions.conf +- [websms](src/websms) Use `$_POST` since `file_get_contents("php://input")` cannot handle multipart/form-data +- [websms](src/websms) Allow IP addr filtering behind proxy by using HTTP_X_FORWARDED_FOR +- [websms](src/websms) websmsd.php parameters are json decoded and searched recursively +- [websms](src/websms) Also support Zadarma POST parameters in websms.class.inc +- [websms](src/websms) Started WebSMS (separate) documentation +- [autoban](src/autoban) Fixed new bug in autoban.class.inc +- [autoban](src/autoban) Added conf sample file autoban.conf.sample + +# 0.2.0 + +- [repo](src) Now reorganize repo files according to which service they provide +- [docker](Dockerfile) alpine 3.10.3 released so now build using alpine:3.10 +- [docker](Dockerfile) Added Health check +- [docker](src/docker) Introduce a `SIGTERM` trap in `docker-entrypoint.sh` allowing graceful container termination with `exit.d` script execution +- [docker](src/docker) [docker-service.sh](src/docker/bin/docker-service.sh) now also take switches -n and -l. +- [docker](src/docker) We now create directory structure when an empty volume is mounted at /srv. +- [asterisk](src/asterisk) Based on live testing updated templates in pjsip_wizard.conf +- [asterisk](src/asterisk) Now use extensions-local.conf to keep all local configurations +- [asterisk](src/asterisk) Fixed typo in rtp.conf +- [websms](src/websms) Retired service sms/d which has been succeeded by websms/d +- [websms](src/websms) New verify POST request in websms.class.inc +- [websms](src/websms) New check source IP address in websms.class.inc +- [autoban](src/autoban) New service Autoban, which listens to security AMI events and dynamically configures nftables to block abusing IPs. +- [autoban](src/autoban) autoban.class.inc (formerly nft.class.inc) is now state less +- [autoban](src/autoban) Restricting Autoban's AMI access to a minimum +- [autoban](src/autoban) Autoban now has `repeatmult` punishing repeat offenders progressively more severely +- [autoban](src/autoban) Autoban now use nftables timeouts +- [autoban](src/autoban) Added `entry.d` and `exit.d` scripts so that the `nft` state is loaded/saved at container startup/shutdown. + +# 0.1.0 + +- [docker](Dockerfile) Using alpine:3.9 since for alpine:3.10 there are dependency errors reported when asterisk starts. +- [privatedial](src/privatedial) minivm-send bash script simplify minivm configuration. diff --git a/asterisk/docker-asterisk-0.9.9/Dockerfile b/asterisk/docker-asterisk-0.9.9/Dockerfile new file mode 100644 index 0000000..4cadd30 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/Dockerfile @@ -0,0 +1,176 @@ +ARG DIST=alpine +ARG REL=latest + + +# +# +# target: mini +# +# asterisk, minimal +# +# + +FROM $DIST:$REL AS mini +LABEL maintainer=mlan + +ENV SVDIR=/etc/service \ + DOCKER_PERSIST_DIR=/srv \ + DOCKER_BIN_DIR=/usr/local/bin \ + DOCKER_ENTRY_DIR=/etc/docker/entry.d \ + DOCKER_EXIT_DIR=/etc/docker/exit.d \ + DOCKER_PHP_DIR=/usr/share/php7 \ + DOCKER_SPOOL_DIR=/var/spool/asterisk \ + DOCKER_CONF_DIR=/etc/asterisk \ + DOCKER_LOG_DIR=/var/log/asterisk \ + DOCKER_LIB_DIR=/var/lib/asterisk \ + DOCKER_DL_DIR=/usr/lib/asterisk/modules \ + DOCKER_NFT_DIR=/var/lib/nftables \ + DOCKER_SEED_CONF_DIR=/usr/share/asterisk/config \ + DOCKER_SEED_NFT_DIR=/etc/nftables \ + DOCKER_SSL_DIR=/etc/ssl \ + ACME_POSTHOOK="sv restart asterisk" \ + SYSLOG_LEVEL=4 \ + SYSLOG_OPTIONS=-SDt \ + WEBSMSD_PORT=80 +ENV DOCKER_MOH_DIR=$DOCKER_LIB_DIR/moh \ + DOCKER_ACME_SSL_DIR=$DOCKER_SSL_DIR/acme \ + DOCKER_APPL_SSL_DIR=$DOCKER_SSL_DIR/asterisk + +# +# Copy utility scripts including docker-entrypoint.sh to image +# + +COPY src/*/bin $DOCKER_BIN_DIR/ +COPY src/*/entry.d $DOCKER_ENTRY_DIR/ +COPY src/*/exit.d $DOCKER_EXIT_DIR/ +COPY src/*/php $DOCKER_PHP_DIR/ +COPY sub/*/php $DOCKER_PHP_DIR/ +COPY src/*/config $DOCKER_SEED_CONF_DIR/ +COPY src/*/nft $DOCKER_SEED_NFT_DIR/ + +# +# Facilitate persistent storage and install asterisk +# + +RUN source docker-common.sh \ + && source docker-config.sh \ + && dc_persist_dirs \ + $DOCKER_APPL_SSL_DIR \ + $DOCKER_CONF_DIR \ + $DOCKER_LOG_DIR \ + $DOCKER_MOH_DIR \ + $DOCKER_NFT_DIR \ + $DOCKER_SPOOL_DIR \ + && mkdir -p $DOCKER_ACME_SSL_DIR \ + && apk --no-cache --update add \ + asterisk + +# +# Entrypoint, how container is run +# + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["asterisk", "-fp"] + + +# +# +# target: base +# +# asterisk add-ons: WebSMS and AutoBan +# +# + +FROM mini AS base + +# +# Install packages used by the add-ons and register services +# + +RUN apk --no-cache --update add \ + asterisk-curl \ + asterisk-speex \ + asterisk-srtp \ + openssl \ + curl \ + php7 \ + php7-curl \ + php7-json \ + runit \ + bash \ + nftables \ + jq \ + && docker-service.sh \ + "syslogd -nO- -l$SYSLOG_LEVEL $SYSLOG_OPTIONS" \ + "crond -f -c /etc/crontabs" \ + "-q asterisk -pf" \ + "-n websmsd php -S 0.0.0.0:$WEBSMSD_PORT -t $DOCKER_PHP_DIR websmsd.php" \ + "$DOCKER_PHP_DIR/autoband.php" \ + && mkdir -p /var/spool/asterisk/staging + +# +# Have runit's runsvdir start all services +# + +CMD runsvdir -P ${SVDIR} + +# +# Check if all services are running +# + +HEALTHCHECK CMD sv status ${SVDIR}/* + + +# +# +# target: full +# +# Add sounds and configure ALSA pluging to PulseAudio +# +# + +FROM base AS full + +# +# Copy patent-encumbered codecs to image +# + +COPY sub/*/module $DOCKER_DL_DIR/ + +# +# Install packages supporting audio +# + +RUN apk --no-cache --update add \ + asterisk-alsa \ + alsa-plugins-pulse \ + asterisk-sounds-en \ + sox + +# +# +# target: extra +# +# all asterisk packages +# +# + +FROM full AS xtra + +# +# Install all asterisk packages +# + +RUN apk --no-cache --update add \ + asterisk-cdr-mysql \ + asterisk-dahdi \ + asterisk-doc \ + asterisk-fax \ + asterisk-mobile \ + asterisk-odbc \ + asterisk-pgsql \ + asterisk-tds \ + asterisk-dbg \ + asterisk-dev \ + asterisk-sounds-moh \ + man-pages diff --git a/asterisk/docker-asterisk-0.9.9/LICENSE.txt b/asterisk/docker-asterisk-0.9.9/LICENSE.txt new file mode 100644 index 0000000..f33bc26 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 mlan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/asterisk/docker-asterisk-0.9.9/Makefile b/asterisk/docker-asterisk-0.9.9/Makefile new file mode 100644 index 0000000..1c52384 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/Makefile @@ -0,0 +1,79 @@ +# Makefile +# +# build +# + +-include *.mk + +BLD_ARG ?= --build-arg DIST=alpine --build-arg REL=3.13 +BLD_REPO ?= fgst/asterisk +BLD_VER ?= latest +BLD_TGT ?= full +BLD_CVER ?= ast160 +BLD_DNLD ?= curl -o + +TST_REPO ?= $(BLD_REPO) +TST_VER ?= $(BLD_VER) +TST_ENV ?= -C test +TST_TGTE ?= $(addprefix test-,all diff down env htop logs sh sv up) +TST_INDX ?= 1 2 3 4 +TST_TGTI ?= $(addprefix test_,$(TST_INDX)) $(addprefix test-up_,$(TST_INDX)) + +export TST_REPO TST_VER + +_version = $(if $(findstring $(BLD_TGT),$(1)),\ +$(if $(findstring latest,$(2)),latest $(1),$(2) $(1)-$(2)),\ +$(if $(findstring latest,$(2)),$(1),$(1)-$(2))) + +build-all: build_mini build_base build_full build_xtra + +build: build_$(BLD_TGT) + +build_%: pre_build + docker build $(BLD_ARG) --target $* \ + $(addprefix --tag $(BLD_REPO):,$(call _version,$*,$(BLD_VER))) . + +pre_build: Dockerfile pre_autoban pre_codecs + + +pre_autoban: sub/autoban/php/ami.class.inc + + +pre_codecs: codec_g723.so codec_g729.so + + +sub/autoban/php/ami.class.inc: submodule + mkdir -p $(@D) + ln -f sub/module/phpami/src/Ami.php $@ + +submodule: + git submodule update --init --recursive + +codec_%.so: sub/codecs/download/codec_%-$(BLD_CVER).so + mkdir -p sub/codecs/module + ln -f $< sub/codecs/module/$@ + +.PRECIOUS: sub/codecs/download/%.so + +sub/codecs/download/%.so: + mkdir -p $(@D) + $(BLD_DNLD) $@ http://asterisk.hosting.lv/bin/$*-gcc4-glibc-x86_64-core2.so + chmod 0755 $@ + +variables: + make -pn | grep -A1 "^# makefile"| grep -v "^#\|^--" | sort | uniq + +ps: + docker ps -a + +prune: + docker image prune -f + +clean: + docker images | grep $(BLD_REPO) | awk '{print $$1 ":" $$2}' | uniq | xargs docker rmi + +$(TST_TGTE): + ${MAKE} $(TST_ENV) $@ + +$(TST_TGTI): + ${MAKE} $(TST_ENV) $@ diff --git a/asterisk/docker-asterisk-0.9.9/README.md b/asterisk/docker-asterisk-0.9.9/README.md new file mode 100644 index 0000000..38539af --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/README.md @@ -0,0 +1,405 @@ +# The `mlan/asterisk` repository + +![travis-ci test](https://img.shields.io/travis/com/mlan/docker-asterisk.svg?label=build&style=flat-square&logo=travis) +![docker build](https://img.shields.io/docker/cloud/build/mlan/asterisk.svg?label=build&style=flat-square&logo=docker) +![image size](https://img.shields.io/docker/image-size/mlan/asterisk/latest.svg?label=size&style=flat-square&logo=docker) +![docker pulls](https://img.shields.io/docker/pulls/mlan/asterisk.svg?label=pulls&style=flat-square&logo=docker) +![docker stars](https://img.shields.io/docker/stars/mlan/asterisk.svg?label=stars&style=flat-square&logo=docker) +![github stars](https://img.shields.io/github/stars/mlan/docker-asterisk.svg?label=stars&style=popout-square&logo=github) + +This (non official) repository provides dockerized Asterisk PBX. + +## Features + +- [Asterisk](http://www.asterisk.org/) powering IP PBX systems and VoIP gateways +- [PrivateDial](src/privatedial), customizable Asterisk configuration +- [WebSMS](src/websms), send and receive messages, SMS, over HTTP +- [AutoBan](src/autoban), a built in intrusion detection and prevention system +- Additionally provide the [G.729](https://en.wikipedia.org/wiki/G.729) and [G.723.1](https://en.wikipedia.org/wiki/G.723.1) audio codecs +- Small image size based on [Alpine Linux](https://alpinelinux.org/) +- [Demo](#docker-compose-example) based on `docker-compose.yml` and `Makefile` files +- Automatic integration of [Let’s Encrypt](https://letsencrypt.org/) LTS certificates using the reverse proxy [Traefik](https://docs.traefik.io/) +- Persistent storage facilitated by configuration and run data being consolidated under `/srv` +- [Container audio](#container-audio) using the pulse socket of the host +- Use [runit](http://smarden.org/runit/), providing an init scheme and service supervision +- Health check +- Log directed to docker daemon with configurable level +- Multi-staged build providing the images `mini`, `base`, `full` and `xtra` + +## Tags + +The MAJOR.MINOR.PATCH [SemVer](https://semver.org/) +is used. In addition to the three number version number you can use two or +one number versions numbers, which refers to the latest version of the +sub series. The tag `latest` references the build based on the latest commit to the repository. + +The `mlan/asterisk` repository contains a multi staged built. You select which build using the appropriate tag from `mini`, `base`, `full` and `xtra`. The image with the tag `mini` only contains Asterisk itself. +The `base` tag also include support for TLS, logging, WebSMS and AutoBan. `full` adds support for console audio. The `xtra` tag includes all Asterisk packages. + + To exemplify the usage of the tags, lets assume that the latest version is `1.0.0`. In this case `latest`, `1.0.0`, `1.0`, `1`, `full`, `full-1.0.0`, `full-1.0` and `full-1` all identify the same image. + +# Usage + +There are many things to consider when configuring Asterisk and its components. We discuss some fundamentals here and in the separate documentation for the [add-ons](#add-ons). + +If you want to test the image right away, probably the best way is to clone the [github](https://github.com/mlan/docker-asterisk) repository and run the demo therein. + +```bash +git clone https://github.com/mlan/docker-asterisk.git +``` + +## Docker compose example + +An example of how to configure an VoIP SIP server using docker compose is given below. + +```yaml +version: '3' + +services: + tele: + image: mlan/asterisk + network_mode: bridge # Only here to help testing + cap_add: + - sys_ptrace # Only here to help testing + - net_admin # Allow NFT, used by AutoBan + - net_raw # Allow NFT, used by AutoBan + ports: + - "${SMS_PORT-8080}:${WEBSMSD_PORT:-80}" # WEBSMSD port mapping + - "5060:5060/udp" # SIP UDP port + - "5060:5060" # SIP TCP port + - "5061:5061" # SIP TLS port + - "10000-10099:10000-10099/udp" # RTP ports + environment: + - SYSLOG_LEVEL=${SYSLOG_LEVEL-4} # Logging + - HOSTNAME=${TELE_SRV-tele}.${DOMAIN-docker.localhost} + - PULSE_SERVER=unix:/run/pulse/socket # Use host audio + - PULSE_COOKIE=/run/pulse/cookie # Use host audio + - WEBSMSD_PORT=${WEBSMSD_PORT-80} # WEBSMSD internal port + volumes: + - tele-conf:/srv # Persistent storage + - ./pulse:/run/pulse:rshared # Use host audio + - /etc/localtime:/etc/localtime:ro # Use host timezone + +volumes: + tele-conf: # Persistent storage +``` + +This repository contains a `demo` directory which hold the `docker-compose.yml` file as well as a `Makefile` which might come handy. From within the `demo` directory you can start the container simply by typing: + +```bash +make up +``` + +The you can connect to the asterisk command line interface (CLI) running inside the container by typing + +```bash +make cli +``` + +From the Asterisk CLI you can type + +```bash +pjsip show endpoints +``` + +to see the endpoints (soft phones) that are configured in the `/etc/asterisk/pjsip_endpoint.conf` configuration file that comes with the image by default. + +When you are done testing you can destroy the test container by typing + +```bash +make destroy +``` + +## Environment variables + +Despite the fact that Asterisk is configured using configuration files, there is a handful of environmental variables that controls the behavior of services within the `mlan/asterisk` container. These services are logging, the management of TLS certificates, and the WebSMS add-on. + +| Variable | Default | Description | +| ----------------------------------------- | --------------- | ------------------------------------------------------------ | +| [SYSLOG_LEVEL](#logging-syslog_level) | 4 | Logging level, from 0 to 8. 0 is the least, whereas, 8 is the most log outputs. | +| SYSLOG_OPTIONS | -SDt | S: smaller output, D: drop duplicates, t: Strip client-generated timestamps. | +| [ACME_FILE](#acme_file) | /acme/acme.json | File that contains TLS certificates, provided by [Let's encrypt](https://letsencrypt.org/) using [Traefik](https://docs.traefik.io/). | +| HOSTNAME | $(hostname) | Used to identify the relevant TLS certificates in ACME_FILE. | +| [TLS_CERTDAYS](#tls_keybits-tls_certdays) | 30 | Self-signed TLS certificate validity duration in days. | +| [TLS_KEYBITS](#tls_keybits-tls_certdays) | 2048 | Self-signed TLS key length in bits. | +| [WEBSMSD_PORT](#websmsd_port) | 80 | PHP web server port, used by WebSMS. Undefined or non-numeric, will disable the PHP web server. | + +## Configuration files + +Asterisk and its modules are configured using several configuration files which are typically found in `/etc/asterisk`. The `/mlan/asterisk` image includes a collection of sample configuration files which can serve as starting point for your system. + +Some of the configuration files provided does not contain any user specific data and might initially be left unmodified. These files are: + +| File name | Description | +| ---------------- | ------------------------------------------------------------ | +| alsa.conf | Open Sound System (ALSA) console driver configuration | +| asterisk.conf | Asterisk global configuration including; debug, run-as-user and directory structure | +| ccss.conf | Call Completion Supplementary Services configuration | +| cli_aliases.conf | Asterisk Command Line Interface aliases | +| features.conf | Call Features (transfer, monitor, etc) configuration | +| indications.conf | Location specific tone indications | +| logger.conf | Logging configuration | +| modules.conf | Module Loader configuration | +| musiconhold.conf | Music on Hold configuration | +| pjproject.conf | Common pjproject options | +| rtp.conf | RTP configuration including port range | + +The configuration files mentioned above are perhaps not the ones that require the most attention. The configuration files defining key aspects of the Asterisk server — like for instance, the call flow and SIP trunk and phone details — is the concern of the add-on [PrivateDial](#privatedial). Please refer to its separate [documentation](src/privatedial/doc/privatedial.md) for details. + +## Persistent storage + +By default, docker will store the configuration and run data within the container. This has the drawback that the configuration and state of the applications are lost together with the container, should it be deleted. It can therefore be a good idea to use docker volumes and mount the configuration and spool directories directories on such volumes so that the data will survive a container deletion. + +To facilitate such approach, to achieve persistent storage, the configuration and spool directories of the services has been consolidated under `/srv`. The applications running inside the container still finds files in their usual locations since symbolic links are placed in these locations pointing back to `/srv`. With this approach simply mounting a docker volume at `/srv` let you keep application configuration and state persistent. + +The volume `tele-conf` in the [demo](#docker-compose-example), which uses `docker-compose`, described above, achieves this. Mounting a volume using the docker CLI, can look like this: + +``` +docker run -d -v tele-conf:/srv ... mlan/asterisk +``` + +## Seeding procedure + +The `mlan/asterisk` image contains sample configuration files placed in a seeding directory. The actual configuration directory is empty. When the container starts, the configuration directory, `etc/asterisk` , is scanned. If it is found to be empty, sample configuration files from the seeding directory are copied to the configuration directory. + +The seeding procedure will leave any existing configuration untouched. If configuration files are found, nothing is copied or modified during start up. Only when `etc/asterisk` is found to be empty, will seeding files be copied. This behavior should keep your conflagration safe also when upgrading to a new version of the `mlan/asterisk` image. Should a new version of the `mlan/asterisk` image come with interesting updates to any sample configuration files, it needs to manually be copied or merged with the present configuration files. + +## Logging `SYSLOG_LEVEL` + +The level of output for logging is in the range of 0 to 8. 1 means emergency logging only, 2 for alert messages, 3 for critical messages only, 4 for error or worse, 5 for warning or worse, 6 for notice or worse, 7 for info or worse, 8 debug. Default: `SYSLOG_LEVEL=4` + +# Add-ons + +The `mlan/asterisk` repository contains add-ons that utilizes and extends the already impressive capabilities of Asterisk. + +## [PrivateDial](src/privatedial) + +PrivateDial is a suite of [Asterisk configuration files](https://wiki.asterisk.org/wiki/display/AST/Asterisk+Configuration+Files). This configuration is tailored to residential use cases, supporting the capabilities of mobile smart phones, that is, voice, video, instant messaging or SMS, and voice mail delivered by email. + +It uses the [PJSIP](https://www.pjsip.org/) [channel driver](https://wiki.asterisk.org/wiki/display/AST/Configuring+res_pjsip) and therefore natively support simultaneous connection of several soft-phones to each user account/endpoint. + +The underlying design idea is to separate the dial plan functionality from the user data. To achieve this all user specific data has been pushed out from the main `extensions.conf` file. + +## [AutoBan](src/autoban) + +AutoBan is an intrusion detection and prevention system which is built-in the `mlan/asterisk` image. The intrusion detection is achieved by Asterisk itself. Asterisk generates security events which AutoBan listens to on the AMI interface. + +When security events occurs AutoBan start to monitor the source IP address. Should repeated security events occur intrusion prevention is activated. Intrusion prevention is achieved by AutoBan asking the Linux kernel firewall [nftables](https://netfilter.org/projects/nftables/) to drop packages from offending source IP addresses. + +## [WebSMS](src/websms) + +Asterisk supports SMS to be sent and received using the extended SIP method; MESSAGE, natively. Still many [Internet Telephony Service Providers](https://wikipedia.org/wiki/Internet_telephony_service_provider) (ITSP) does not support this method, but instead used a web [API](https://en.wikipedia.org/wiki/Application_programming_interface) based on [HTTP](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol) requests. This leaves your Asterisk server without a mechanisms to exchange SMS externally. + +The WebSMS service bridges this limitation, with the help of two components. The first, `websmsd`, which waits for incoming SMS to be sent from your ITSP and once received, forwards it to Asterisk. The second, `websms`, is used by Asterisk to send outgoing SMS to your ITSP. + +#### `WEBSMSD_PORT` + +WebSMS uses PHP's integrated web server. The environment variable `WEBSMSD_PORT=80` determinate which port the web server listens to. If `WEBSMSD_PORT` is undefined or non-numeric the PHP web server is disabled, and consequently, WebSMS too. Disabling the web server might be desired in scenarios when the container runs in host mode and there are concerns with port number clashes with other services running on the host. + +# Networking +SIP networking is quite complex and there is many things that can go wrong. We try to offer some guidance by discussing some fundamentals here. + +## SIP protocol + +The [Session Initiation Protocol (SIP)](https://en.wikipedia.org/wiki/Session_Initiation_Protocol) is a [signaling protocol](https://en.wikipedia.org/wiki/Signaling_protocol) used for initiating, maintaining, and terminating real-time sessions that include voice, video and messaging applications. + +### Transports, UDP, TCP and TLS + +SIP is designed to be independent of the underlying [transport layer](https://en.wikipedia.org/wiki/Transport_layer) protocol, and can be used with the [User Datagram Protocol](https://en.wikipedia.org/wiki/User_Datagram_Protocol) (UDP), the [Transmission Control Protocol](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) (TCP), and the [Stream Control Transmission Protocol](https://en.wikipedia.org/wiki/Stream_Control_Transmission_Protocol) (SCTP). For secure transmissions of SIP messages over insecure network links, the protocol may be encrypted with [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security) (TLS). For the transmission of media streams (voice, video) the [Session Description Protocol](https://en.wikipedia.org/wiki/Session_Description_Protocol) (SDP) payload carried in SIP messages typically employs the [Real-time Transport Protocol](https://en.wikipedia.org/wiki/Real-time_Transport_Protocol) (RTP) or the [Secure Real-time Transport Protocol](https://en.wikipedia.org/wiki/Secure_Real-time_Transport_Protocol) (SRTP). + +When sending an audio stream it is far better to lose a packet than to have a packet retransmitted, causing excessive jitter in the packet timing. Audio is real-time and requires a protocol like UDP to work correctly. Packet loss does not break audio, it only reduces the quality. Therefore it is no surprise that RTP is built on top of UDP; an connection-less protocol. + +TCP is a connection-oriented protocol as it establishes an end to end connection between computers before transferring the data. TCP is therefore, by contrast, ideal for SIP signaling. The somewhat unexpected fact that most SIP communication uses UDP should not discourage you from choosing TCP when possible. TCP often provide more reliable contacts with endpoints/phones than UDP. + +TLS, operating as an application protocol layered directly over TCP, protects against attackers who try to listen on the signaling link but it does not provide end-to-end security to prevent espionage and law enforcement interception, as the encryption is only hop-by-hop and every single intermediate proxy has to be trusted. + +The media streams which are separate connections from the signaling stream, may be encrypted with the [Secure Real-time Transport Protocol](https://en.wikipedia.org/wiki/Secure_Real-time_Transport_Protocol) (SRTP). The key exchange for SRTP is performed with [SDES](https://en.wikipedia.org/wiki/SDES), or with [DTSL](https://en.wikipedia.org/wiki/Datagram_Transport_Layer_Security). + +### Ports, 5060, 5061 and 10000-20000 + +SIP traffic typically use the [port numbers](https://en.wikipedia.org/wiki/Port_number) 5060 or 5061. Port 5060 is commonly used for non-encrypted signaling traffic, i.e., TCP or UDP, whereas port 5061 is used for encrypted, TLS, traffic. + +RTP uses a dynamic port range generally between 10000-20000. This range can usually be customized on the client to suit differing firewall configurations or other concerns. + +## Docker, iptables and docker-proxy + +When publishing ports on a docker container, using the default `bridge` networking, two things happen; routing rules are updated in the Linux kernel firewall and a proxy processes are stated. The current networking implementation in docker (19.03.8), built on the aged [iptables](https://en.wikipedia.org/wiki/Iptables) and docker-proxy, cannot publish port *ranges*, but instead publish them one by one. + +Normally RTP uses the port range 10000-20000, encompassing 10001 ports. This is problematic since, updating the firewall rules 10001 times and starting 10001 proxy processes can take unacceptable long time (minutes) and can cause the container startup to stall. Longterm this limitation will be addressed, since it is inevitable that docker networking will have to be redesigned. But right now we have to work around this imitation and we describe two ways to address this here. + +First, you can use the `host` network mode (`docker run --network host …`). The host network mode does not use the docker-proxy and does not need to set up routing rules in the firewall. The downside is that a container stated in this way cannot communicate on any of the docker networks. + +Second, you can stay with the default or user-defined `bridge` mode and instead limit the RTP port range to something manageable say 10000-10099, or up to 10000-10999. This actually seems to work in practice, at least with some trunk providers (ITSP). The RTP port range is configured in `rtp.conf` + +```ini +[general] +rtpstart = 10000 +rtpend = 10099 +``` + +## Network address translation (NAT) + +[Network address translation (NAT)](https://en.wikipedia.org/wiki/Network_address_translation) is a method of remapping one IP [address space](https://en.wikipedia.org/wiki/Address_space) into another by modifying the [network address](https://en.wikipedia.org/wiki/Network_address) information in the [IP header](https://en.wikipedia.org/wiki/IP_header) of packets while they are in transit across a traffic [routing device](https://en.wikipedia.org/wiki/Router_(computing)). Network environments often results in NAT being used. On the one hand, the SIP server we deploy using `mlan/asterisk` often uses a Docker [bridge network](https://docs.docker.com/network/bridge/), connecting Dockers local network with the one the host is connected to. On the other, SIP clients running on mobile phones often end up connect to remote local networks. + +### SIP server address + +To provide SIP clients with the external network address of a server behind NAT it can explicitly be defined on the transport used which is configured in `pjsip_transport.conf` + +```ini +[t_wan](!) +type = transport +bind = 0.0.0.0:5060 +domain = example.com +external_signaling_address = sip.example.com +external_media_address = sip.example.com +``` + +### SIP client contact rewrite + +For endpoints connected to remote local networks you need the following parameters which are defined in `pjsip_wizard.conf` + +```ini +[_nat](!) +endpoint/rewrite_contact = yes +endpoint/direct_media = no +endpoint/rtp_symmetric = yes +endpoint/bind_rtp_to_media_address = yes +``` + +### Strict RTP protection + +Strict RTP learning is not compatible with NAT. When enabled, RTP media packets that have passed NAT will be dropped, resulting in an one way audio experience. Disable strict RTP learning in `rtp.conf` + +```ini +[general] +strictrtp = no +``` + +### ICE, STUN, and TURN + +Sometimes there is a need for other more elaborate NAT traversal methods; [ICE, STUN or TURN](https://wiki.asterisk.org/wiki/display/~jcolp/ICE,+STUN,+and+TURN+Support). A treatment of these is a little bit out of scope for this text. + +## Security - Privacy and integrity + +[Transport Layer Security](http://en.wikipedia.org/wiki/Transport_Layer_Security) (TLS) provides encryption for call signaling. A excellent guide for setting up TLS between Asterisk and a SIP client, involving creating key files, modifying Asterisk's SIP configuration to enable TLS, creating a SIP endpoint/user that's capable of TLS, and modifying the SIP client to connect to Asterisk over TLS, can be found here [Secure Calling Tutorial](https://wiki.asterisk.org/wiki/display/AST/Secure+Calling+Tutorial). + +The PrivateDial configuration is already set up to provide both UDP and TCP transport. TLS, SDES and DTSL SRTP are also prepared, but a [TLS/SSL server certificate](https://en.wikipedia.org/wiki/Public_key_certificate) and key are needed for their activation. If the certificate and key do not exist when the container starts a [self-signed certificate](https://en.wikipedia.org/wiki/Self-signed_certificate) and private key will automatically be generated. + +#### `TLS_KEYBITS`, `TLS_CERTDAYS` + +The private key length and self-signed certificate validity duration can be configured using the environment variables: `TLS_KEYBITS=2048` and `TLS_CERTDAYS=30`. + +### Let’s Encrypt LTS certificates using Traefik + +[Let’s Encrypt](https://letsencrypt.org/) provide free, automated, authorized certificates when you can demonstrate control over your domain. Automatic Certificate Management Environment (ACME) is the protocol used for such demonstration. + +There are many agents and applications that supports ACME, e.g., [certbot](https://certbot.eff.org/). The reverse proxy [Traefik](https://docs.traefik.io/) also supports ACME. `mlan/asterisk` can use the LTS certificates Traefik has acquired. + +#### `ACME_FILE`, `ACME_POSTHOOK` + +The `mlan/asterisk` image looks for the file `ACME_FILE=/acme/acme.json` at container startup. If it is found certificates within this file are extracted. If the host or domain name of one of those certificates matches `HOSTNAME=$(hostname)` or `DOMAIN=${HOSTNAME#*.}` it will be used by the TLS transport. Moreover, the `ACME_FILE` will be monitored and should it change the certificates will be exported anew. So when Traefik renews its certificates Asterisk will automatically also have access to the new certificate. + +Once the certificates and keys have been updated, we run the command in the environment variable `ACME_POSTHOOK="sv restart asterisk"`. Asterisk needs to be restarted to reload the transport, i.e., LTS parameters to be updated. If automatic restarting of Asterisk is not desired, set `ACME_POSTHOOK=` to empty. + +Using Traefik's certificates will work "out of the box" simply by making sure that the `/acme` directory in the Traefik container is also is mounted in the `mlan/asterisk` container. + +```bash +docker run -d -v proxy-acme:/acme:ro mlan/asterisk +``` + +Note, if the target certificate Common Name (CN) or Subject Alternate Name (SAN) is changed the container needs to be restarted. + +## Security - Intrusion prevention + +Attempts by attackers to crack SIP passwords and hijack SIP accounts are very common. Most likely the server will have to fend off thousands of attempts every day. here we mention three means to improve intrusion prevention; obscurity by using non-standard ports, SIP passwords strength, and [AutoBan](src/autoban); an Intrusion Detection and Prevention System. + +### Obscurity by using non-standard ports + +When using non-standard ports the amount of attacks drop significantly, so it might be considered whenever practical. When changing port numbers they need to be updated both for docker and asterisk. To exemplify, assume we want to use 5560 for UDP and TCP and 5561 for TLS, in which case we update the configuration in two places: + +- docker or docker-compose, e.g., `docker run -p "5560-5561:5560-5561" -p "5560:5560/udp" …` +- asterisk transport in `pjsip_transport.conf` (`pjsip.conf`), e.g. `bind = 0.0.0.0:5560` and `bind = 0.0.0.0:5561` + +### SIP passwords strength + +It’s recommended that the minimum strength of a password used in a SIP digests are at least 8 characters long, preferably 10 characters, and have characters that include lower and upper case alphabetic, a number and a non-alphabetic, non-numeric ASCII character, see [SIP Password Security - How much is yours worth?](https://www.sipsorcery.com/mainsite/Help/SIPPasswordSecurity) + +## Codec modules + +Asterisk natively provides several audio and video [codec modules](https://wiki.asterisk.org/wiki/display/AST/Codec+Modules). Additionally the [G.729](https://en.wikipedia.org/wiki/G.729) and [G.723.1](https://en.wikipedia.org/wiki/G.723.1) audio codecs has been copied to the image. These are maintained by [arkadijs/asterisk-g72x](https://github.com/arkadijs/asterisk-g72x). + +# Container audio + +The `mlan/asterisk` container supports two-way audio using [PulseAudio](https://www.freedesktop.org/wiki/Software/PulseAudio/). This allows you to use the Asterisk console channel to do some management or debugging. The audio stream is passed between the container and host by sharing the user's pulse UNIX socket. + +The method described here was chosen since it allows audio to be enabled on an already running container. The method involves a directory `./pulse:/run/pulse:rshared` on the host being mounted in the container, see the [compose example](#docker-compose-example), and environment variables being set within the container, allowing pulse to locate the socket; `PULSE_SERVER=unix:/run/pulse/socket` and cookie; `PULSE_COOKIE=/run/pulse/cookie`. To arrange the pulse directory on the host, from a shell, run: + +```sh +mkdir -p pulse +touch pulse/socket +``` + +Without additional steps, the bind mount and environment variables described above achieve nothing. This is fine since most of the time we are not interested in sharing audio with the container. But should there come a time when we want to enable the audio, we can do so in 3 simple steps: 1) Mount the user's pulse socket in the host directory `./pulse/socket` and, 2) copy the user's pulse cookie there too, `./pulse/cookie`. 3) Have asterisk, running inside the container, load the `chan_alsa.so` module. From a shell running on the host, these steps are: + +```sh +sudo mount --bind $(pactl info | sed '1!d;s/.*:\s*//g') pulse/socket +cp -f ${PULSE_COOKIE-$HOME/.config/pulse/cookie} pulse/cookie +docker-compose exec $(SRV_NAME) asterisk -rx 'module load chan_alsa.so' +``` + +A limitation of this approach is that you need sudo/root access do be able to bind mount on the host. And, naturally, there needs to be a pulse server running on the host for any of this to work. + +## Playing with audio + +You can use the [demo](#docker-compose-example) above, and once the container is running, enable audio by typing, from within the `demo` directory: + +```bash +make sound_enable +``` + +Now you can tryout any of the trivial sound checks, for example: + +```bash +make sound_5 +``` + +To disable audio, type: + +```bash +make sound_disable +``` + +# Implementation + +Here some implementation details are presented. + +## Container init scheme + +The `mlan/asterisk` container use [runit](http://smarden.org/runit/), providing an init scheme and service supervision, allowing multiple services to be started. + +When the container is started, execution is handed over to the script [`docker-entrypoint.sh`](src/docker/bin/docker-entrypoint.sh). It has 4 stages; 0) *register* the SIGTERM [signal (IPC)](https://en.wikipedia.org/wiki/Signal_(IPC)) handler, which is programmed to run all exit scripts in `DOCKER_EXIT_DIR=/etc/docker/exit.d` and terminate all services, 1) *run* all entry scripts in `DOCKER_ENTRY_DIR=/etc/docker/entry.d`, 2) *start* services registered in `/etc/service/`, 3) *wait* forever, allowing the signal handler to catch the SIGTERM and run the exit scripts and terminate all services. + +The entry scripts are responsible for tasks like, seeding configurations, register services and reading state files. These scripts are run before the services are started. + +There is also exit script that take care of tasks like, writing state files. These scripts are run when docker sends the SIGTERM signal to the main process in the container. Both `docker stop` and `docker kill --signal=TERM` sends SIGTERM. + +## Build assembly + +The entry and exit scripts, discussed above, as well as other utility scrips are copied to the image during the build phase. The source file tree was designed to facilitate simple scanning, using wild-card matching, of source-module directories for files that should be copied to image. Directory names indicate its file types so they can be copied to the correct locations. The code snippet in the `Dockerfile` which achieves this is show below. + +```dockerfile +COPY src/*/bin $DOCKER_BIN_DIR/ +COPY src/*/entry.d $DOCKER_ENTRY_DIR/ +COPY src/*/exit.d $DOCKER_EXIT_DIR/ +COPY src/*/php $DOCKER_PHP_DIR/ +COPY sub/*/php $DOCKER_PHP_DIR/ +COPY src/*/config $DOCKER_SEED_CONF_DIR/ +COPY src/*/nft $DOCKER_SEED_NFT_DIR/ +COPY sub/*/module $DOCKER_DL_DIR/ +``` + +There is also a mechanism for excluding files from being copied to the image from some source-module directories. Source-module directories to be excluded are listed in the file [`.dockerignore`](https://docs.docker.com/engine/reference/builder/#dockerignore-file). Since we don't want files from the module `notused` we list it in the `.dockerignore` file: + +```sh +src/notused +``` diff --git a/asterisk/docker-asterisk-0.9.9/ROADMAP.md b/asterisk/docker-asterisk-0.9.9/ROADMAP.md new file mode 100644 index 0000000..f9b2498 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/ROADMAP.md @@ -0,0 +1,31 @@ +# Road map + +## PrivateDial + +- Make IVR custom-able + +## MiniVM + +The application [MinivmGreet()](https://wiki.asterisk.org/wiki/display/AST/Asterisk+16+Application_MinivmGreet) is broken. Now it only plays the "temp" message. +Consider fixing the code in [app_minivm.c](https://github.com/asterisk/asterisk/blob/8f5534a68a01ad3fbe6b1920c8ab160fc3b4df89/apps/app_minivm.c) lines 2326-2345 and file a patch. + +## Upgrade utility + +- Shell utility that helps upgrading config files. + +## Music on hold + +- Script that converts sound files to wav 8000 Hz mono. + +## AutoBan + +- Add option to get reverse DNS using gethostbyaddr($ip); in `show who`. +- Perhaps replace entry.d/ with /etc/conf.d/nftables? +- Allow intervals, eg 192.168.1.1-192.168.1.200, in blacklist and whitelist. + +## WebSMS + +## Asterisk modules + +- Check what modules are needed and avoid loading others. This will help get rid of error messages during startup. + diff --git a/asterisk/docker-asterisk-0.9.9/demo/.env b/asterisk/docker-asterisk-0.9.9/demo/.env new file mode 100644 index 0000000..1f4428e --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/demo/.env @@ -0,0 +1,6 @@ +COMPOSE_PROJECT_NAME=demo +SYSLOG_LEVEL=8 +DOMAIN=example.com +TELE_SRV=tele +SMS_PORT=8080 +WEBSMSD_PORT=80 diff --git a/asterisk/docker-asterisk-0.9.9/demo/.gitignore b/asterisk/docker-asterisk-0.9.9/demo/.gitignore new file mode 100644 index 0000000..3a31952 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/demo/.gitignore @@ -0,0 +1 @@ +pulse/ diff --git a/asterisk/docker-asterisk-0.9.9/demo/Makefile b/asterisk/docker-asterisk-0.9.9/demo/Makefile new file mode 100644 index 0000000..88125ee --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/demo/Makefile @@ -0,0 +1,166 @@ +-include *.mk .env .init.env + +_ip = $(shell docker inspect -f \ + '{{range .NetworkSettings.Networks}}{{println .IPAddress}}{{end}}' \ + $(1) | head -n1) + +SRV_NAME ?= tele +CNT_NAME ?= $(COMPOSE_PROJECT_NAME)_$(SRV_NAME)_1 +CNT_CLI ?= asterisk -rvvvddd + +SIPS_URL ?= $(call _ip,$(CNT_NAME)):5061 + +SMS_HOST ?= 127.0.0.1:8080 +SMS_URL1 ?= /hook/1 +SMS_URL2 ?= /hook/2 +SMS_FROM ?= +15017122661 +SMS_TO ?= +12025550160 +SMS_BODY ?= This is a test message, sent $$(date), with special chars: ☺ [$$\"\\];; and 4 additional lines:%0A1%0A2%0A3%0A4. + + +variables: + make -pn | grep -A1 "^# makefile"| grep -v "^#\|^--" | sort | uniq + +init: up + +ps: + docker-compose ps + +up: + docker-compose up -d + +start: + docker-compose start + +stop: + docker-compose stop + +down: + docker-compose down + +destroy: + docker-compose down -v + +config: + docker-compose config + +wait_%: + sleep 10 + +pw: + dd if=/dev/random count=1 bs=8 2>/dev/null | base64 | sed -e 's/=*$$//' + #od -vAn -N4 -tu4 < /dev/urandom + +sms0: + curl -i $(SMS_HOST)$(SMS_URL1) -G \ + --data-urlencode "zd_echo=$(shell date)" + @echo + +sms1: + curl -i $(SMS_HOST)$(SMS_URL1) -X POST \ + --data-urlencode "To=$(SMS_TO)" \ + --data-urlencode "From=$(SMS_FROM)" \ + --data "Body=$(SMS_BODY)" + +sms2: + curl -i $(SMS_HOST)$(SMS_URL2) -X POST \ + --data-urlencode "To=$(SMS_TO)" \ + --data-urlencode "From=$(SMS_FROM)" \ + --data "Body=$(SMS_BODY)" + +logs: + docker container logs $(CNT_NAME) + +sh: + docker-compose exec $(SRV_NAME) bash + +cli: + docker-compose exec $(SRV_NAME) $(CNT_CLI) + +diff: + docker container diff $(CNT_NAME) + +top: + docker container top $(CNT_NAME) + +env: + docker-compose exec $(SRV_NAME) env + +sv: + docker-compose exec $(SRV_NAME) sh -c 'sv status $$SVDIR/*' + +nft: + docker-compose exec $(SRV_NAME) nft list ruleset + +autoban: + docker-compose exec $(SRV_NAME) autoban show + +htop: tools_install + docker-compose exec $(SRV_NAME) htop + +ipcs: + docker-compose exec $(SRV_NAME) ipcs + +logger: + docker-compose exec $(SRV_NAME) asterisk -rx \ + 'logger add channel console notice,warning,error,verbose' + +restart_%: + docker-compose exec $(SRV_NAME) sv restart $* + +apk_list: + docker-compose exec $(SRV_NAME) /bin/sh -c 'for pkg in $$(apk info 2>/dev/null); do printf "%9s %s\n" $$(apk info -s $$pkg 2>/dev/null | sed -n "2{p;q}") $$pkg; done | sort' + +apk_add_%: + docker-compose exec $(SRV_NAME) apk -q --no-cache --update add $* + +tools_install: + docker-compose exec $(SRV_NAME) apk --no-cache --update add \ + nano lsof htop openldap-clients bind-tools iputils strace util-linux \ + pulseaudio-utils alsa-utils + +xdebug_install: + docker-compose exec $(SRV_NAME) apk --no-cache --update add \ + php7-pecl-xdebug + docker-compose exec $(SRV_NAME) sed -i '1 a xdebug.profiler_enable = 1' /etc/php7/php.ini + docker-compose exec $(SRV_NAME) sed -i '2 a zend_extension=xdebug.so' /etc/php7/conf.d/xdebug.ini + docker-compose exec $(SRV_NAME) sv restart websmsd autoband + +xdebug_getdata: + docker cp $(CNT_NAME):tmp/. local/xdebug + +sips_test: + docker run --rm -it --network bridge drwetter/testssl.sh $(SIPS_URL) || true + +sound_enable: pulse/socket + cp -f $${PULSE_COOKIE-$$HOME/.config/pulse/cookie} pulse/cookie + sudo mount --bind $$(pactl info | sed '1!d;s/.*:\s*//g') pulse/socket + docker-compose exec $(SRV_NAME) asterisk -rx 'module load chan_alsa.so' || true + +sound_disable: + rm pulse/cookie + sudo umount pulse/socket + +pulse/socket: + mkdir -p pulse + touch pulse/socket + +sound_1: + docker-compose exec $(SRV_NAME) play -nq -t alsa synth 1 sine 300 + +sound_2: + docker-compose exec $(SRV_NAME) play -q /var/lib/asterisk/sounds/en/hello-world.gsm + +sound_3: apk_add_alsa-utils + docker-compose exec $(SRV_NAME) aplay -Dpulse /usr/share/sounds/alsa/Front_Right.wav + +sound_4: apk_add_pulseaudio-utils + docker-compose exec $(SRV_NAME) paplay /usr/share/sounds/alsa/Front_Center.wav + +sound_5: + docker-compose exec $(SRV_NAME) asterisk -rx \ + 'channel originate console/+12025550160@dp_entry_call_inout application playback hello-world' + +sound_6: + docker-compose exec $(SRV_NAME) asterisk -rx 'console dial t@dp_ivr_recgreet' + diff --git a/asterisk/docker-asterisk-0.9.9/demo/docker-compose.yml b/asterisk/docker-asterisk-0.9.9/demo/docker-compose.yml new file mode 100644 index 0000000..1e7379f --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/demo/docker-compose.yml @@ -0,0 +1,29 @@ +version: '3' + +services: + tele: + image: fgst/asterisk:base + network_mode: bridge # Only here to help testing + cap_add: + - sys_ptrace # Only here to help testing + - net_admin # Allow NFT, used by AutoBan + - net_raw # Allow NFT, used by AutoBan + ports: + - "${SMS_PORT-8080}:${WEBSMSD_PORT:-80}" # WEBSMSD port mapping + - "5060:5060/udp" # SIP UDP port + - "5060:5060" # SIP TCP port + - "5061:5061" # SIP TLS port + - "10000-10099:10000-10099/udp" # RTP ports + environment: + - SYSLOG_LEVEL=${SYSLOG_LEVEL-4} # Logging + - HOSTNAME=${TELE_SRV-tele}.${DOMAIN-docker.localhost} + - PULSE_SERVER=unix:/run/pulse/socket # Use host audio + - PULSE_COOKIE=/run/pulse/cookie # Use host audio + - WEBSMSD_PORT=${WEBSMSD_PORT-80} # WEBSMSD internal port + volumes: + - tele-conf:/srv # Persistent storage + - ./pulse:/run/pulse:rshared # Use host audio + - /etc/localtime:/etc/localtime:ro # Use host timezone + +volumes: + tele-conf: # Persistent storage diff --git a/asterisk/docker-asterisk-0.9.9/hooks/build b/asterisk/docker-asterisk-0.9.9/hooks/build new file mode 100644 index 0000000..31d8e6e --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/hooks/build @@ -0,0 +1,24 @@ +#!/bin/bash +# hooks/build +# $DOCKER_REPO and $DOCKER_TAG are injected into the build environment + +# +# Identify build target +# +echo "hooks/build called with IMAGE_NAME=${DOCKER_REPO}:${DOCKER_TAG}, so we will run:" +case "${DOCKER_TAG}" in + mini*) bld_target=mini ;; + base*) bld_target=base ;; + full*|latest*|[0-9]*) bld_target=full ;; + xtra*) bld_target=xtra ;; + *) + echo "NOTHING since we do not know how to build with tag=${DOCKER_TAG}" + exit 1 + ;; +esac + +# +# Build image +# +echo "docker build --target $bld_target -t ${DOCKER_REPO}:${DOCKER_TAG} ." +docker build --target $bld_target -t ${DOCKER_REPO}:${DOCKER_TAG} . diff --git a/asterisk/docker-asterisk-0.9.9/hooks/pre_build b/asterisk/docker-asterisk-0.9.9/hooks/pre_build new file mode 100644 index 0000000..2ba1d40 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/hooks/pre_build @@ -0,0 +1,17 @@ +#!/bin/bash +# hooks/pre_build +# $DOCKER_REPO and $DOCKER_TAG are injected into the docker hub build environment + +# +# Explore the docker hub build environment +# +uname -a || true +for utility in apt curl wget; do + which $utility || true +done +#printenv || true + +# +# make pre_build +# +make pre_build diff --git a/asterisk/docker-asterisk-0.9.9/src/acme/bin/acme-extract.sh b/asterisk/docker-asterisk-0.9.9/src/acme/bin/acme-extract.sh new file mode 100755 index 0000000..3d74c7e --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/acme/bin/acme-extract.sh @@ -0,0 +1,193 @@ +#!/usr/bin/env sh +# Copyright (c) 2017 Brian 'redbeard' Harrington +# +# acme-export.sh - A simple utility to explode a Traefik acme.json file into a +# directory of certificates and a private key +# +# Usage - acme-export.sh /etc/traefik/acme.json /etc/ssl/ +# +# Dependencies - +# util-linux +# openssl +# jq +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# + +# Exit codes: +# 1 - A component is missing or could not be read +# 2 - There was a problem reading acme.json +# 4 - The destination certificate directory does not exist +# 8 - Missing private key + +#set -o errexit +##set -o pipefail +#set -o nounset +#set -o verbose + + +# +# configuration +# +. docker-common.sh + +DOCKER_ACME_SSL_DIR=${DOCKER_ACME_SSL_DIR-/etc/ssl/acme} +ACME_FILE=${ACME_FILE-/acme/acme.json} + +CMD_DECODE_BASE64="base64 -d" + +# +# functions +# +usage() { echo "$(basename $0) " ;} + +test_args() { + # when called by inotifyd the first argument is the single character + # event descriptor, lets drop it + dc_log 7 "Called with args $@" + [ $# -ge 0 ] && [ ${#1} -eq 1 ] && shift + readonly acmefile="${1-$ACME_FILE}" + readonly certdir="${2-$DOCKER_ACME_SSL_DIR}" +} + +test_dependencies() { + # Allow us to exit on a missing jq binary + if dc_is_installed jq; then + dc_log 7 "The package jq is installed." + else + dc_log 4 "You must have the binary jq to use this." + exit 1 + fi +} + +test_acmefile() { + if [ ! -r "${acmefile}" ]; then + dc_log 4 "There was a problem reading from (${acmefile}). We need to read this file to explode the JSON bundle... exiting." + exit 2 + fi +} + +test_certdir() { + if [ ! -d "${certdir}" ]; then + dc_log 4 "Path ${certdir} does not seem to be a directory. We need a directory in which to explode the JSON bundle... exiting." + exit 4 + fi +} + +make_certdirs() { + # If they do not exist, create the needed subdirectories for our assets + # and place each in a variable for later use, normalizing the path + mkdir -p "${certdir}/certs" "${certdir}/private" + pdir="${certdir}/private" + cdir="${certdir}/certs" +} + +bad_acme() { + dc_log 4 "There was a problem parsing your acme.json file." + exit 2 +} + +read_letsencryptkey() { + # look for key assuming acme v2 format + priv=$(jq -e -r '.[].Account.PrivateKey' "${acmefile}" 2>/dev/null) + if [ $? -eq 0 ]; then + acmeversion=2 + dc_log 7 "Using acme v2 format, the PrivateKey was found in ${acmefile}" + else + # look for key assuming acme v1 format + priv=$(jq -e -r '.Account.PrivateKey' "${acmefile}" 2>/dev/null) + if [ $? -eq 0 ]; then + acmeversion=1 + dc_log 7 "Using acme v1 format, the PrivateKey was found in ${acmefile}" + else + dc_log 4 "There didn't seem to be a private key in ${acmefile}. Please ensure that there is a key in this file and try again." + exit 2 + fi + fi +} + +save_letsencryptkey() { + local keyfile=${pdir}/letsencrypt.key + printf -- \ + "-----BEGIN RSA PRIVATE KEY-----\n%s\n-----END RSA PRIVATE KEY-----\n" \ + ${priv} | fold -w 65 | \ + openssl rsa -inform pem -out $keyfile 2>/dev/null + if [ -e $keyfile ]; then + dc_log 7 "PrivateKey is valid and saved in $keyfile" + else + dc_log 4 "PrivateKey appers NOT to be valid" + exit 2 + fi +} + +read_domains() { + # Process the certificates for each of the domains in acme.json + case $acmeversion in + 1) jq_filter='.Certificates[].Domain.Main' ;; + 2) jq_filter='.[].Certificates[].domain.main' ;; + esac + domains=$(jq -r $jq_filter $acmefile) + if [ -n "$domains" ]; then + dc_log 7 "Extracting private key and cert bundle for domains $domains." + else + dc_log 4 "Unable to find any domains in $acmefile." + exit 2 + fi +} + +# +# Traefik stores a cert bundle for each domain. Within this cert +# bundle there is both proper the certificate and the Let's Encrypt CA +# +save_certs() { + dc_log 5 "Extracting private keys and cert bundles in ${acmefile}" + case $acmeversion in + 1) + jq_crtfilter='.Certificates[] | select (.Domain.Main == $domain )| .Certificate' + jq_keyfilter='.Certificates[] | select (.Domain.Main == $domain )| .Key' + ;; + 2) + jq_crtfilter='.[].Certificates[] | select (.domain.main == $domain )| .certificate' + jq_keyfilter='.[].Certificates[] | select (.domain.main == $domain )| .key' + ;; + esac + for domain in $domains; do + crt=$(jq -e -r --arg domain "$domain" "$jq_crtfilter" $acmefile) || bad_acme + echo "${crt}" | ${CMD_DECODE_BASE64} > "${cdir}/${domain}.crt" + key=$(jq -e -r --arg domain "$domain" "$jq_keyfilter" $acmefile) || bad_acme + echo "${key}" | ${CMD_DECODE_BASE64} > "${pdir}/${domain}.key" + done +} + +# +# Run command in ACME_POSTHOOK if it contain a valid command and runsvdir is running. +# +run_posthook() { + if (pidof runsvdir >/dev/null && [ -n "$ACME_POSTHOOK" ] && command -v $ACME_POSTHOOK >/dev/null); then + local out=$(eval "$ACME_POSTHOOK" 2>&1) + [ -n "$out" ] && dc_log 7 "$ACME_POSTHOOK : $out" + fi +} + +# +# run +# +test_args $@ +test_dependencies +test_acmefile +test_certdir +read_letsencryptkey +make_certdirs +save_letsencryptkey +read_domains +save_certs +run_posthook diff --git a/asterisk/docker-asterisk-0.9.9/src/acme/entry.d/10-acme-common b/asterisk/docker-asterisk-0.9.9/src/acme/entry.d/10-acme-common new file mode 100755 index 0000000..85b6307 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/acme/entry.d/10-acme-common @@ -0,0 +1,58 @@ +#!/bin/sh +# +# 10-acme-common +# +# Define variables and functions used during container initialization. +# +# Variables defined in Dockerfile +# DOCKER_ACME_SSL_DIR DOCKER_APPL_SSL_DIR +# +ACME_FILE=${ACME_FILE-/acme/acme.json} +HOSTNAME=${HOSTNAME-$(hostname)} +DOMAIN=${HOSTNAME#*.} +DOCKER_APPL_SSL_CERT=${DOCKER_APPL_SSL_CERT-$DOCKER_APPL_SSL_DIR/cert.pem} +DOCKER_APPL_SSL_KEY=${DOCKER_APPL_SSL_KEY-$DOCKER_APPL_SSL_DIR/priv_key.pem} +DOCKER_ACME_SSL_H_CERT=$DOCKER_ACME_SSL_DIR/certs/${HOSTNAME}.crt +DOCKER_ACME_SSL_H_KEY=$DOCKER_ACME_SSL_DIR/private/${HOSTNAME}.key +DOCKER_ACME_SSL_D_CERT=$DOCKER_ACME_SSL_DIR/certs/${DOMAIN}.crt +DOCKER_ACME_SSL_D_KEY=$DOCKER_ACME_SSL_DIR/private/${DOMAIN}.key + +# +# Setup monitoring of ACME_FILE +# +acme_monitor_tls_cert() { + if (dc_is_installed jq && (dc_is_command inotifyd || dc_is_command inotifywait)); then + if [ -s $ACME_FILE ]; then + # run acme-extract.sh on cnt creation (and every time the json file changes) + dc_log 5 "Setup ACME TLS certificate monitoring" + if dc_is_command inotifyd; then + docker-service.sh "-n acme $(which inotifyd) $(which acme-extract.sh) $ACME_FILE:c" + else + docker-service.sh "-n acme sh -c \"while $(which inotifywait) -e close_write $ACME_FILE; do $(which acme-extract.sh); done\"" + fi + # acme-extract.sh reports to logger but it is yet to be started so this run will be quiet + acme-extract.sh $ACME_FILE $DOCKER_ACME_SSL_DIR + fi + else + dc_log 5 "Not all required pkgs installed so cannot setup ACME TLS certificate monitoring" + fi +} + +# +# Arrange sym-links to support both host and domain certificates. +# +acme_symlink_tls_cert() { + if ([ -r $DOCKER_ACME_SSL_H_CERT ] && [ -r $DOCKER_ACME_SSL_H_KEY ]); then + dc_log 5 "Setting up ACME TLS certificate for host $HOSTNAME" + mkdir -p $DOCKER_APPL_SSL_DIR + ln -sf $DOCKER_ACME_SSL_H_CERT $DOCKER_APPL_SSL_CERT + ln -sf $DOCKER_ACME_SSL_H_KEY $DOCKER_APPL_SSL_KEY + else + if ([ -r $DOCKER_ACME_SSL_D_CERT ] && [ -r $DOCKER_ACME_SSL_D_KEY ]); then + dc_log 5 "Setting up ACME TLS certificate for domain $DOMAIN" + mkdir -p $DOCKER_APPL_SSL_DIR + ln -sf $DOCKER_ACME_SSL_D_CERT $DOCKER_APPL_SSL_CERT + ln -sf $DOCKER_ACME_SSL_D_KEY $DOCKER_APPL_SSL_KEY + fi + fi +} diff --git a/asterisk/docker-asterisk-0.9.9/src/acme/entry.d/50-acme-monitor-tlscert b/asterisk/docker-asterisk-0.9.9/src/acme/entry.d/50-acme-monitor-tlscert new file mode 100755 index 0000000..051a583 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/acme/entry.d/50-acme-monitor-tlscert @@ -0,0 +1,13 @@ +#!/bin/sh +# +# 50-acme-monitor-tlscert +# +# Functions defined in: +# 10-acme-common +# + +# +# Setup ACME monitor and arrange certificate symbolic links +# +acme_monitor_tls_cert +acme_symlink_tls_cert diff --git a/asterisk/docker-asterisk-0.9.9/src/asterisk/config/alsa.conf b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/alsa.conf new file mode 100644 index 0000000..00035c3 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/alsa.conf @@ -0,0 +1,2 @@ +[general] +;noaudiocapture = true diff --git a/asterisk/docker-asterisk-0.9.9/src/asterisk/config/asterisk.conf b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/asterisk.conf new file mode 100644 index 0000000..d50e4d1 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/asterisk.conf @@ -0,0 +1,22 @@ +[options] +; If we want to start Asterisk with a default verbosity for the verbose +; or debug logger channel types, then we use these settings (by default +; they are disabled). +;verbose = 3 +;debug = 3 + +; User and group to run asterisk as. NOTE: This will require changes to +; directory and device permissions. +;runuser = asterisk ; The user to run as. The default is root. +;rungroup = asterisk ; The group to run as. The default is root + +;defaultlanguage = us + +; Transmit silence while a channel is in a waiting state, a recording only +; state, or when DTMF is being generated. Note that the silence internally is +; generated in raw signed linear format. This means that it must be transcoded +; into the native format of the channel before it can be sent to the device. +; It is for this reason that this is optional, as it may result in requiring a +; temporary codec translation path for a channel that may not otherwise require +; one. +;transmit_silence=yes diff --git a/asterisk/docker-asterisk-0.9.9/src/asterisk/config/ccss.conf b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/ccss.conf new file mode 100644 index 0000000..e69de29 diff --git a/asterisk/docker-asterisk-0.9.9/src/asterisk/config/cli_aliases.conf b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/cli_aliases.conf new file mode 100644 index 0000000..b71d18c --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/cli_aliases.conf @@ -0,0 +1,16 @@ +; +; CLI Aliases configuration +; +; This module also registers a "cli show aliases" CLI command to list +; configured CLI aliases. + +[general] +template = friendly ; By default, include friendly aliases + +[friendly] +hangup request=channel request hangup +originate=channel originate +help=core show help +pri intense debug span=pri set debug intense span +reload=module reload +pjsip reload=module reload res_pjsip.so res_pjsip_authenticator_digest.so res_pjsip_endpoint_identifier_ip.so res_pjsip_mwi.so res_pjsip_notify.so res_pjsip_outbound_publish.so res_pjsip_publish_asterisk.so res_pjsip_outbound_registration.so diff --git a/asterisk/docker-asterisk-0.9.9/src/asterisk/config/features.conf b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/features.conf new file mode 100644 index 0000000..e69de29 diff --git a/asterisk/docker-asterisk-0.9.9/src/asterisk/config/indications.conf b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/indications.conf new file mode 100644 index 0000000..d0641cd --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/indications.conf @@ -0,0 +1,737 @@ +; +; indications.conf +; +; Configuration file for location specific tone indications +; + +; +; NOTE: +; When adding countries to this file, please keep them in alphabetical +; order according to the 2-character country codes! +; +; The [general] category is for certain global variables. +; All other categories are interpreted as location specific indications +; + +[general] +country=us ; default location + + +; [example] +; description = string +; The full name of your country, in English. +; ringcadence = num[,num]* +; List of durations the physical bell rings. +; dial = tonelist +; Set of tones to be played when one picks up the hook. +; busy = tonelist +; Set of tones played when the receiving end is busy. +; congestion = tonelist +; Set of tones played when there is some congestion (on the network?) +; callwaiting = tonelist +; Set of tones played when there is a call waiting in the background. +; dialrecall = tonelist +; Not well defined; many phone systems play a recall dial tone after hook +; flash. +; record = tonelist +; Set of tones played when call recording is in progress. +; info = tonelist +; Set of tones played with special information messages (e.g., "number is +; out of service") +; 'name' = tonelist +; Every other variable will be available as a shortcut for the "PlayList" command +; but will not be used automatically by Asterisk. +; +; +; The tonelist itself is defined by a comma-separated sequence of elements. +; Each element consist of a frequency (f) with an optional duration (in ms) +; attached to it (f/duration). The frequency component may be a mixture of two +; frequencies (f1+f2) or a frequency modulated by another frequency (f1*f2). +; The implicit modulation depth is fixed at 90%, though. +; If the list element starts with a !, that element is NOT repeated, +; therefore, only if all elements start with !, the tonelist is time-limited, +; all others will repeat indefinitely. +; +; concisely: +; element = [!]freq[+|*freq2][/duration] +; tonelist = element[,element]* +; + +[at] +description = Austria +ringcadence = 1000,5000 +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +dial = 420 +busy = 420/400,0/400 +ring = 420/1000,0/5000 +congestion = 420/200,0/200 +callwaiting = 420/40,0/1960 +dialrecall = 420 +; RECORDTONE - not specified +record = 1400/80,0/14920 +info = 950/330,1450/330,1850/330,0/1000 +stutter = 380+420 + +[au] +description = Australia +; Reference http://www.acif.org.au/__data/page/3303/S002_2001.pdf +; Normal Ring +ringcadence = 400,200,400,2000 +; Distinctive Ring 1 - Forwarded Calls +; 400,400,200,200,400,1400 +; Distinctive Ring 2 - Selective Ring 2 + Operator + Recall +; 400,400,200,2000 +; Distinctive Ring 3 - Multiple Subscriber Number 1 +; 200,200,400,2200 +; Distinctive Ring 4 - Selective Ring 1 + Centrex +; 400,2600 +; Distinctive Ring 5 - Selective Ring 3 +; 400,400,200,400,200,1400 +; Distinctive Ring 6 - Multiple Subscriber Number 2 +; 200,400,200,200,400,1600 +; Distinctive Ring 7 - Multiple Subscriber Number 3 + Data Privacy +; 200,400,200,400,200,1600 +; Tones +dial = 413+438 +busy = 425/375,0/375 +ring = 413+438/400,0/200,413+438/400,0/2000 +; XXX Congestion: Should reduce by 10 db every other cadence XXX +congestion = 425/375,0/375,420/375,0/375 +callwaiting = 425/200,0/200,425/200,0/4400 +dialrecall = 413+438 +; Record tone used for Call Intrusion/Recording or Conference +record = !425/1000,!0/15000,425/360,0/15000 +info = 425/2500,0/500 +; Other Australian Tones +; The STD "pips" indicate the call is not an untimed local call +std = !525/100,!0/100,!525/100,!0/100,!525/100,!0/100,!525/100,!0/100,!525/100 +; Facility confirmation tone (eg. Call Forward Activated) +facility = 425 +; Message Waiting "stutter" dialtone +stutter = 413+438/100,0/40 +; Ringtone for calls to Telstra mobiles +ringmobile = 400+450/400,0/200,400+450/400,0/2000 + +[bg] +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +description = Bulgaria +ringcadence = 1000,4000 +; +dial = 425 +busy = 425/500,0/500 +ring = 425/1000,0/4000 +congestion = 425/250,0/250 +callwaiting = 425/150,0/150,425/150,0/4000 +dialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 +record = 1400/425,0/15000 +info = 950/330,1400/330,1800/330,0/1000 +stutter = 425/1500,0/100 + +[br] +description = Brazil +ringcadence = 1000,4000 +dial = 425 +busy = 425/250,0/250 +ring = 425/1000,0/4000 +congestion = 425/250,0/250,425/750,0/250 +callwaiting = 425/50,0/1000 +; Dialrecall not used in Brazil standard (using UK standard) +dialrecall = 350+440 +; Record tone is not used in Brazil, use busy tone +record = 425/250,0/250 +; Info not used in Brazil standard (using UK standard) +info = 950/330,1400/330,1800/330 +stutter = 350+440 + +[be] +description = Belgium +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +ringcadence = 1000,3000 +dial = 425 +busy = 425/500,0/500 +ring = 425/1000,0/3000 +congestion = 425/167,0/167 +callwaiting = 1400/175,0/175,1400/175,0/3500 +; DIALRECALL - not specified +dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440 +; RECORDTONE - not specified +record = 1400/500,0/15000 +info = 900/330,1400/330,1800/330,0/1000 +stutter = 425/1000,0/250 + +[ch] +description = Switzerland +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +ringcadence = 1000,4000 +dial = 425 +busy = 425/500,0/500 +ring = 425/1000,0/4000 +congestion = 425/200,0/200 +callwaiting = 425/200,0/200,425/200,0/4000 +; DIALRECALL - not specified +dialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 +; RECORDTONE - not specified +record = 1400/80,0/15000 +info = 950/330,1400/330,1800/330,0/1000 +stutter = 425+340/1100,0/1100 + +[cl] +description = Chile +; According to specs from Telefonica CTC Chile +ringcadence = 1000,3000 +dial = 400 +busy = 400/500,0/500 +ring = 400/1000,0/3000 +congestion = 400/200,0/200 +callwaiting = 400/250,0/8750 +dialrecall = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400 +record = 1400/500,0/15000 +info = 950/333,1400/333,1800/333,0/1000 +stutter = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400 + +[cn] +description = China +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +ringcadence = 1000,4000 +dial = 450 +busy = 450/350,0/350 +ring = 450/1000,0/4000 +congestion = 450/700,0/700 +callwaiting = 450/400,0/4000 +dialrecall = 450 +record = 950/400,0/10000 +info = 450/100,0/100,450/100,0/100,450/100,0/100,450/400,0/400 +; STUTTER - not specified +stutter = 450+425 + +[cz] +description = Czech Republic +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +ringcadence = 1000,4000 +dial = 425/330,0/330,425/660,0/660 +busy = 425/330,0/330 +ring = 425/1000,0/4000 +congestion = 425/165,0/165 +callwaiting = 425/330,0/9000 +; DIALRECALL - not specified +dialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425/330,0/330,425/660,0/660 +; RECORDTONE - not specified +record = 1400/500,0/14000 +info = 950/330,0/30,1400/330,0/30,1800/330,0/1000 +; STUTTER - not specified +stutter = 425/450,0/50 + +[de] +description = Germany +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +ringcadence = 1000,4000 +dial = 425 +busy = 425/480,0/480 +ring = 425/1000,0/4000 +congestion = 425/240,0/240 +callwaiting = !425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,!0/5000,!425/200,!0/200,!425/200,0 +; DIALRECALL - not specified +dialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 +; RECORDTONE - not specified +record = 1400/80,0/15000 +info = 950/330,1400/330,1800/330,0/1000 +stutter = 425+400 + +[dk] +description = Denmark +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +ringcadence = 1000,4000 +dial = 425 +busy = 425/500,0/500 +ring = 425/1000,0/4000 +congestion = 425/200,0/200 +callwaiting = !425/200,!0/600,!425/200,!0/3000,!425/200,!0/200,!425/200,0 +; DIALRECALL - not specified +dialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 +; RECORDTONE - not specified +record = 1400/80,0/15000 +info = 950/330,1400/330,1800/330,0/1000 +; STUTTER - not specified +stutter = 425/450,0/50 + +[ee] +description = Estonia +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +ringcadence = 1000,4000 +dial = 425 +busy = 425/300,0/300 +ring = 425/1000,0/4000 +congestion = 425/200,0/200 +; CALLWAIT not in accordance to ITU +callwaiting = 950/650,0/325,950/325,0/30,1400/1300,0/2600 +; DIALRECALL - not specified +dialrecall = 425/650,0/25 +; RECORDTONE - not specified +record = 1400/500,0/15000 +; INFO not in accordance to ITU +info = 950/650,0/325,950/325,0/30,1400/1300,0/2600 +; STUTTER not specified +stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 + +[es] +description = Spain +ringcadence = 1500,3000 +dial = 425 +busy = 425/200,0/200 +ring = 425/1500,0/3000 +congestion = 425/200,0/200,425/200,0/200,425/200,0/600 +callwaiting = 425/175,0/175,425/175,0/3500 +dialrecall = !425/200,!0/200,!425/200,!0/200,!425/200,!0/200,425 +record = 1400/500,0/15000 +info = 950/330,0/1000 +dialout = 500 +; STUTTER not specified +stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 + + +[fi] +description = Finland +ringcadence = 1000,4000 +dial = 425 +busy = 425/300,0/300 +ring = 425/1000,0/4000 +congestion = 425/200,0/200 +callwaiting = 425/150,0/150,425/150,0/8000 +dialrecall = 425/650,0/25 +record = 1400/500,0/15000 +info = 950/650,0/325,950/325,0/30,1400/1300,0/2600 +stutter = 425/650,0/25 + +[fr] +description = France +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +ringcadence = 1500,3500 +; Dialtone can also be 440+330 +dial = 440 +busy = 440/500,0/500 +ring = 440/1500,0/3500 +; CONGESTION - not specified +congestion = 440/250,0/250 +callwait = 440/300,0/10000 +; DIALRECALL - not specified +dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440 +; RECORDTONE - not specified +record = 1400/500,0/15000 +info = !950/330,!1400/330,!1800/330 +stutter = !440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,!440/100,!0/100,440 + +[gr] +description = Greece +ringcadence = 1000,4000 +dial = 425/200,0/300,425/700,0/800 +busy = 425/300,0/300 +ring = 425/1000,0/4000 +congestion = 425/200,0/200 +callwaiting = 425/150,0/150,425/150,0/8000 +dialrecall = 425/650,0/25 +record = 1400/400,0/15000 +info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0 +stutter = 425/650,0/25 + +[hu] +description = Hungary +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +ringcadence = 1250,3750 +dial = 425 +busy = 425/300,0/300 +ring = 425/1250,0/3750 +congestion = 425/300,0/300 +callwaiting = 425/40,0/1960 +dialrecall = 425+450 +; RECORDTONE - not specified +record = 1400/400,0/15000 +info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0 +stutter = 350+375+400 + +[il] +description = Israel +ringcadence = 1000,3000 +dial = 414 +busy = 414/500,0/500 +ring = 414/1000,0/3000 +congestion = 414/250,0/250 +callwaiting = 414/100,0/100,414/100,0/100,414/600,0/3000 +dialrecall = !414/100,!0/100,!414/100,!0/100,!414/100,!0/100,414 +record = 1400/500,0/15000 +info = 1000/330,1400/330,1800/330,0/1000 +stutter = !414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,!414/160,!0/160,414 + + +[in] +description = India +ringcadence = 400,200,400,2000 +dial = 400*25 +busy = 400/750,0/750 +ring = 400*25/400,0/200,400*25/400,0/2000 +congestion = 400/250,0/250 +callwaiting = 400/200,0/100,400/200,0/7500 +dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440 +record = 1400/500,0/15000 +info = !950/330,!1400/330,!1800/330,0/1000 +stutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,400*25 + +[it] +description = Italy +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +ringcadence = 1000,4000 +dial = 425/200,0/200,425/600,0/1000 +busy = 425/500,0/500 +ring = 425/1000,0/4000 +congestion = 425/200,0/200 +callwaiting = 425/400,0/100,425/250,0/100,425/150,0/14000 +dialrecall = 470/400,425/400 +record = 1400/400,0/15000 +info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0 +stutter = 470/400,425/400 + +[lt] +description = Lithuania +ringcadence = 1000,4000 +dial = 425 +busy = 425/350,0/350 +ring = 425/1000,0/4000 +congestion = 425/200,0/200 +callwaiting = 425/150,0/150,425/150,0/4000 +; DIALRECALL - not specified +dialrecall = 425/500,0/50 +; RECORDTONE - not specified +record = 1400/500,0/15000 +info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0 +; STUTTER - not specified +stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 + +[jp] +description = Japan +ringcadence = 1000,2000 +dial = 400 +busy = 400/500,0/500 +ring = 400+15/1000,0/2000 +congestion = 400/500,0/500 +callwaiting = 400+16/500,0/8000 +dialrecall = !400/200,!0/200,!400/200,!0/200,!400/200,!0/200,400 +record = 1400/500,0/15000 +info = !950/330,!1400/330,!1800/330,0 +stutter = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400 + +[mx] +description = Mexico +ringcadence = 2000,4000 +dial = 425 +busy = 425/250,0/250 +ring = 425/1000,0/4000 +congestion = 425/250,0/250 +callwaiting = 425/200,0/600,425/200,0/10000 +dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440 +record = 1400/500,0/15000 +info = 950/330,0/30,1400/330,0/30,1800/330,0/1000 +stutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,425 + +[my] +description = Malaysia +ringcadence = 2000,4000 +dial = 425 +busy = 425/500,0/500 +ring = 425/400,0/200,425/400,0/2000 +congestion = 425/500,0/500 +; STUTTER - not specified +stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 + +[nl] +description = Netherlands +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +ringcadence = 1000,4000 +; Most of these 425's can also be 450's +dial = 425 +busy = 425/500,0/500 +ring = 425/1000,0/4000 +congestion = 425/250,0/250 +callwaiting = 425/500,0/9500 +; DIALRECALL - not specified +dialrecall = 425/500,0/50 +; RECORDTONE - not specified +record = 1400/500,0/15000 +info = 950/330,1400/330,1800/330,0/1000 +stutter = 425/500,0/50 + +[no] +description = Norway +ringcadence = 1000,4000 +dial = 425 +busy = 425/500,0/500 +ring = 425/1000,0/4000 +congestion = 425/200,0/200 +callwaiting = 425/200,0/600,425/200,0/10000 +dialrecall = 470/400,425/400 +record = 1400/400,0/15000 +info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0 +stutter = 470/400,425/400 + +[nz] +description = New Zealand +; Reference = http://www.telepermit.co.nz/TNA102.pdf +ringcadence = 400,200,400,2000 +dial = 400 +busy = 400/500,0/500 +ring = 400+450/400,0/200,400+450/400,0/2000 +congestion = 400/250,0/250 +callwaiting = !400/200,!0/3000,!400/200,!0/3000,!400/200,!0/3000,!400/200 +dialrecall = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400 +record = 1400/425,0/15000 +info = 400/750,0/100,400/750,0/100,400/750,0/100,400/750,0/400 +stutter = !400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,!400/100,!0/100,400 +unobtainable = 400/75,0/100,400/75,0/100,400/75,0/100,400/75,0/400 + +[ph] + +; reference http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf + +description = Philippines +ringcadence = 1000,4000 +dial = 425 +busy = 480+620/500,0/500 +ring = 425+480/1000,0/4000 +congestion = 480+620/250,0/250 +callwaiting = 440/300,0/10000 +; DIALRECALL - not specified +dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440 +; RECORDTONE - not specified +record = 1400/500,0/15000 +; INFO - not specified +info = !950/330,!1400/330,!1800/330,0 +; STUTTER - not specified +stutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,425 + + +[pl] +description = Poland +ringcadence = 1000,4000 +dial = 425 +busy = 425/500,0/500 +ring = 425/1000,0/4000 +congestion = 425/500,0/500 +callwaiting = 425/150,0/150,425/150,0/4000 +; DIALRECALL - not specified +dialrecall = 425/500,0/50 +; RECORDTONE - not specified +record = 1400/500,0/15000 +; 950/1400/1800 3x0.33 on 1.0 off repeated 3 times +info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000 +; STUTTER - not specified +stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 + +[pt] +description = Portugal +ringcadence = 1000,5000 +dial = 425 +busy = 425/500,0/500 +ring = 425/1000,0/5000 +congestion = 425/200,0/200 +callwaiting = 440/300,0/10000 +dialrecall = 425/1000,0/200 +record = 1400/500,0/15000 +info = 950/330,1400/330,1800/330,0/1000 +stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 + +[ru] +; References: +; http://www.minsvyaz.ru/site.shtml?id=1806 +; http://www.aboutphone.info/lib/gost/45-223-2001.html +description = Russian Federation / ex Soviet Union +ringcadence = 1000,4000 +dial = 425 +busy = 425/350,0/350 +ring = 425/1000,0/4000 +congestion = 425/175,0/175 +callwaiting = 425/200,0/5000 +record = 1400/400,0/15000 +info = 950/330,1400/330,1800/330,0/1000 +dialrecall = 425/400,0/40 +stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 + +[se] +description = Sweden +ringcadence = 1000,5000 +dial = 425 +busy = 425/250,0/250 +ring = 425/1000,0/5000 +congestion = 425/250,0/750 +callwaiting = 425/200,0/500,425/200,0/9100 +dialrecall = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 +record = 1400/500,0/15000 +info = !950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,!0/2024,!950/332,!0/24,!1400/332,!0/24,!1800/332,0 +stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 +; stutter = 425/320,0/20 ; Real swedish standard, not used for now + +[sg] +description = Singapore +; Singapore +; Reference: http://www.ida.gov.sg/idaweb/doc/download/I397/ida_ts_pstn1_i4r2.pdf +; Frequency specs are: 425 Hz +/- 20Hz; 24 Hz +/- 2Hz; modulation depth 100%; SIT +/- 50Hz +ringcadence = 400,200,400,2000 +dial = 425 +ring = 425*24/400,0/200,425*24/400,0/2000 ; modulation should be 100%, not 90% +busy = 425/750,0/750 +congestion = 425/250,0/250 +callwaiting = 425*24/300,0/200,425*24/300,0/3200 +stutter = !425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,!425/200,!0/200,!425/600,!0/200,425 +info = 950/330,1400/330,1800/330,0/1000 ; not currently in use acc. to reference +dialrecall = 425*24/500,0/500,425/500,0/2500 ; unspecified in IDA reference, use repeating Holding Tone A,B +record = 1400/500,0/15000 ; unspecified in IDA reference, use 0.5s tone every 15s +; additionally defined in reference +nutone = 425/2500,0/500 +intrusion = 425/250,0/2000 +warning = 425/624,0/4376 ; end of period tone, warning +acceptance = 425/125,0/125 +holdinga = !425*24/500,!0/500 ; followed by holdingb +holdingb = !425/500,!0/2500 + +[th] +description = Thailand +ringcadence = 1000,4000 +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +dial = 400*50 +busy = 400/500,0/500 +ring = 420/1000,0/5000 +congestion = 400/300,0/300 +callwaiting = 1000/400,10000/400,1000/400 +; DIALRECALL - not specified - use special dial tone instead. +dialrecall = 400*50/400,0/100,400*50/400,0/100 +; RECORDTONE - not specified +record = 1400/500,0/15000 +; INFO - specified as an announcement - use special information tones instead +info = 950/330,1400/330,1800/330 +; STUTTER - not specified +stutter = !400/200,!0/200,!400/600,!0/200,!400/200,!0/200,!400/600,!0/200,!400/200,!0/200,!400/600,!0/200,!400/200,!0/200,!400/600,!0/200,400 + +[uk] +description = United Kingdom +ringcadence = 400,200,400,2000 +; These are the official tones taken from BT SIN350. The actual tones +; used by BT include some volume differences so sound slightly different +; from Asterisk-generated ones. +dial = 350+440 +; Special dial is the intermittent dial tone heard when, for example, +; you have a divert active on the line +specialdial = 350+440/750,440/750 +; Busy is also called "Engaged" +busy = 400/375,0/375 +; "Congestion" is the Beep-bip engaged tone +congestion = 400/400,0/350,400/225,0/525 +; "Special Congestion" is not used by BT very often if at all +specialcongestion = 400/200,1004/300 +unobtainable = 400 +ring = 400+450/400,0/200,400+450/400,0/2000 +callwaiting = 400/100,0/4000 +; BT seem to use "Special Call Waiting" rather than just "Call Waiting" tones +specialcallwaiting = 400/250,0/250,400/250,0/250,400/250,0/5000 +; "Pips" used by BT on payphones. (Sounds wrong, but this is what BT claim it +; is and I've not used a payphone for years) +creditexpired = 400/125,0/125 +; These two are used to confirm/reject service requests on exchanges that +; don't do voice announcements. +confirm = 1400 +switching = 400/200,0/400,400/2000,0/400 +; This is the three rising tones Doo-dah-dee "Special Information Tone", +; usually followed by the BT woman saying an appropriate message. +info = 950/330,0/15,1400/330,0/15,1800/330,0/1000 +; Not listed in SIN350 +record = 1400/500,0/60000 +stutter = 350+440/750,440/750 + +[us] +description = United States / North America +ringcadence = 2000,4000 +dial = 350+440 +busy = 480+620/500,0/500 +ring = 440+480/2000,0/4000 +congestion = 480+620/250,0/250 +callwaiting = 440/300,0/10000 +dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440 +record = 1400/500,0/15000 +info = !950/330,!1400/330,!1800/330,0 +stutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440 + +[us-old] +description = United States Circa 1950/ North America +ringcadence = 2000,4000 +dial = 600*120 +busy = 500*100/500,0/500 +ring = 420*40/2000,0/4000 +congestion = 500*100/250,0/250 +callwaiting = 440/300,0/10000 +dialrecall = !600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,600*120 +record = 1400/500,0/15000 +info = !950/330,!1400/330,!1800/330,0 +stutter = !600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,!600*120/100,!0/100,600*120 + +[tw] +description = Taiwan +; http://nemesis.lonestar.org/reference/telecom/signaling/dialtone.html +; http://nemesis.lonestar.org/reference/telecom/signaling/busy.html +; http://www.iproducts.com.tw/ee/kylink/06ky-1000a.htm +; http://www.pbx-manufacturer.com/ky120dx.htm +; http://www.nettwerked.net/tones.txt +; http://www.cisco.com/univercd/cc/td/doc/product/tel_pswt/vco_prod/taiw_sup/taiw2.htm +; +; busy tone 480+620Hz 0.5 sec. on ,0.5 sec. off +; reorder tone 480+620Hz 0.25 sec. on,0.25 sec. off +; ringing tone 440+480Hz 1 sec. on ,2 sec. off +; +ringcadence = 1000,4000 +dial = 350+440 +busy = 480+620/500,0/500 +ring = 440+480/1000,0/2000 +congestion = 480+620/250,0/250 +callwaiting = 350+440/250,0/250,350+440/250,0/3250 +dialrecall = 300/1500,0/500 +record = 1400/500,0/15000 +info = !950/330,!1400/330,!1800/330,0 +stutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440 + +[ve] +; Tone definition source for ve found on +; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf +description = Venezuela / South America +ringcadence = 1000,4000 +dial = 425 +busy = 425/500,0/500 +ring = 425/1000,0/4000 +congestion = 425/250,0/250 +callwaiting = 400+450/300,0/6000 +dialrecall = 425 +record = 1400/500,0/15000 +info = !950/330,!1440/330,!1800/330,0/1000 +; STUTTER - not specified +stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425 + + +[za] +description = South Africa +; http://www.cisco.com/univercd/cc/td/doc/product/tel_pswt/vco_prod/safr_sup/saf02.htm +; (definitions for other countries can also be found there) +; Note, though, that South Africa uses two switch types in their network -- +; Alcatel switches -- mainly in the Western Cape, and Siemens elsewhere. +; The former use 383+417 in dial, ringback etc. The latter use 400*33 +; I've provided both, uncomment the ones you prefer +ringcadence = 400,200,400,2000 +; dial/ring/callwaiting for the Siemens switches: +dial = 400*33 +ring = 400*33/400,0/200,400*33/400,0/2000 +callwaiting = 400*33/250,0/250,400*33/250,0/250,400*33/250,0/250,400*33/250,0/250 +; dial/ring/callwaiting for the Alcatel switches: +; dial = 383+417 +; ring = 383+417/400,0/200,383+417/400,0/2000 +; callwaiting = 383+417/250,0/250,383+417/250,0/250,383+417/250,0/250,383+417/250,0/250 +congestion = 400/250,0/250 +busy = 400/500,0/500 +dialrecall = 350+440 +; XXX Not sure about the RECORDTONE +record = 1400/500,0/10000 +info = 950/330,1400/330,1800/330,0/330 +stutter = !400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,!400*33/100,!0/100,400*33 + diff --git a/asterisk/docker-asterisk-0.9.9/src/asterisk/config/logger.conf b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/logger.conf new file mode 100644 index 0000000..5a49322 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/logger.conf @@ -0,0 +1,8 @@ +[general] + +[logfiles] +syslog.local0 = verbose,notice,warning,error +;console = verbose,notice,warning,error +;messages = notice,warning,error +;full = verbose,notice,warning,error,debug +;security = security diff --git a/asterisk/docker-asterisk-0.9.9/src/asterisk/config/modules.conf b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/modules.conf new file mode 100644 index 0000000..15d7bdd --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/modules.conf @@ -0,0 +1,74 @@ +; +; Asterisk configuration file +; +; Module Loader configuration file +; + +[modules] +autoload=yes +; +; +; If you want, load the GTK console right away. +; +noload => pbx_gtkconsole.so +;load => pbx_gtkconsole.so +; +load => res_musiconhold.so +; +; Load one of: chan_oss, alsa, or console (portaudio). +; By default, load chan_oss only (automatically). +; +;noload => chan_alsa.so +noload => chan_oss.so +noload => chan_console.so + +noload => res_hep.so +noload => res_hep_pjsip.so +noload => res_hep_rtcp.so + +noload => app_agent_pool.so +noload => app_alarmreceiver.so +noload => app_amd.so +noload => app_confbridge.so +noload => app_festival.so +noload => app_followme.so +noload => app_queue.so +noload => app_voicemail.so +noload => cdr_csv.so +noload => cdr_custom.so +noload => cdr_manager.so +noload => cdr_sqlite3_custom.so +noload => cdr_syslog.so +noload => cel_custom.so +noload => cel_manager.so +noload => cel_sqlite3_custom.so +noload => chan_iax2.so +noload => chan_mgcp.so +noload => chan_sip.so +noload => chan_skinny.so +noload => chan_unistim.so +noload => pbx_ael.so +noload => pbx_dundi.so +noload => pbx_lua.so +noload => res_ari_applications.so +noload => res_ari_asterisk.so +noload => res_ari_bridges.so +noload => res_ari_channels.so +noload => res_ari_device_states.so +noload => res_ari_endpoints.so +noload => res_ari_events.so +noload => res_ari_playbacks.so +noload => res_ari_recordings.so +noload => res_ari.so +noload => res_ari_sounds.so +noload => res_calendar.so +noload => res_fax.so +noload => res_parking.so +noload => res_phoneprov.so +noload => res_pjsip_notify.so +noload => res_pjsip_phoneprov_provider.so +noload => res_pjsip_t38.so +noload => res_smdi.so +noload => res_statsd.so +noload => res_stun_monitor.so + diff --git a/asterisk/docker-asterisk-0.9.9/src/asterisk/config/musiconhold.conf b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/musiconhold.conf new file mode 100644 index 0000000..357f46f --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/musiconhold.conf @@ -0,0 +1,6 @@ +[general] + +[default] +mode=files +directory=moh +sort=random diff --git a/asterisk/docker-asterisk-0.9.9/src/asterisk/config/pjproject.conf b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/pjproject.conf new file mode 100644 index 0000000..2a2dee2 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/pjproject.conf @@ -0,0 +1,3 @@ +[startup] +type= +log_level=default diff --git a/asterisk/docker-asterisk-0.9.9/src/asterisk/config/rtp.conf b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/rtp.conf new file mode 100644 index 0000000..091439f --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/asterisk/config/rtp.conf @@ -0,0 +1,11 @@ +[general] +; RTP start and RTP end configure start and end addresses +; docker will stall if we open a large range of ports, since it runs a +; a proxy process of each exposed port +rtpstart = 10000 +rtpend = 10099 +; +; Strict RTP protection will drop packets that have passed NAT. Disable to allow +; remote endpoints connected to LANs. +; +strictrtp = no diff --git a/asterisk/docker-asterisk-0.9.9/src/asterisk/entry.d/50-asterisk-seed-conf b/asterisk/docker-asterisk-0.9.9/src/asterisk/entry.d/50-asterisk-seed-conf new file mode 100755 index 0000000..2b73edf --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/asterisk/entry.d/50-asterisk-seed-conf @@ -0,0 +1,19 @@ +#!/bin/sh +# +# 50-asterisk-seed-conf +# +# Defined in Dockerfile: +# DOCKER_CONF_DIR DOCKER_SEED_CONF_DIR +# + +# +# If DOCKER_CONF_DIR is empty, initialize it with files from +# DOCKER_SEED_CONF_DIR. We don't want to overwrite any files, +# but we only have "cp -u" (only copy newer) in busybox. +# The directory should be empty when we try to copy, +# so this is just an extra precaution. +# +if [ -z "$(ls -A $DOCKER_CONF_DIR 2>/dev/null)" ]; then + dc_log 5 "Seeding asterisk configuration." + cp -p -u $DOCKER_SEED_CONF_DIR/* $DOCKER_CONF_DIR +fi diff --git a/asterisk/docker-asterisk-0.9.9/src/asterisk/entry.d/51-asterisk-generate-tlscert b/asterisk/docker-asterisk-0.9.9/src/asterisk/entry.d/51-asterisk-generate-tlscert new file mode 100755 index 0000000..5e0bc9c --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/asterisk/entry.d/51-asterisk-generate-tlscert @@ -0,0 +1,18 @@ +#!/bin/sh +# +# 51-asterisk-generate-tlscert +# +# Variables defined in 10-acme-common +# DOCKER_APPL_SSL_CERT DOCKER_APPL_SSL_KEY +# + +# +# Generate self signed certificate if but no certificates +# are given. +# +if ([ ! -s $DOCKER_APPL_SSL_CERT ] || [ ! -s $DOCKER_APPL_SSL_KEY ]) && \ + dc_is_installed openssl; then + dc_log 5 "No TLS certificates found, so generating self-signed cert for host $HOSTNAME" + dc_tls_setup_selfsigned_cert $DOCKER_APPL_SSL_CERT $DOCKER_APPL_SSL_KEY +fi + diff --git a/asterisk/docker-asterisk-0.9.9/src/autoban/README.md b/asterisk/docker-asterisk-0.9.9/src/autoban/README.md new file mode 120000 index 0000000..e8d6290 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/autoban/README.md @@ -0,0 +1 @@ +doc/autoban.md \ No newline at end of file diff --git a/asterisk/docker-asterisk-0.9.9/src/autoban/bin/autoban b/asterisk/docker-asterisk-0.9.9/src/autoban/bin/autoban new file mode 120000 index 0000000..f9a1e6f --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/autoban/bin/autoban @@ -0,0 +1 @@ +../../share/php7/autoban.php \ No newline at end of file diff --git a/asterisk/docker-asterisk-0.9.9/src/autoban/config/autoban.conf b/asterisk/docker-asterisk-0.9.9/src/autoban/config/autoban.conf new file mode 100644 index 0000000..bc9a37f --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/autoban/config/autoban.conf @@ -0,0 +1,20 @@ +; +; autoban.conf +; +; This file hold user customization of the AutoBan intrusion detection and +; prevention system. This is a php ini file. Luckily its syntax is similar to +; other asterisk conf files. "yes" and "no" have to be within quotation marks +; otherwise they will be interpreted as Boolean. +; + +[asmanager] +server = 127.0.0.1 +port = 5038 +username = autoban +secret = 6003.438 + +[autoban] +maxcount = 10 +watchtime = 20m +jailtime = 20m +repeatmult = 6 diff --git a/asterisk/docker-asterisk-0.9.9/src/autoban/config/manager.conf b/asterisk/docker-asterisk-0.9.9/src/autoban/config/manager.conf new file mode 100644 index 0000000..f7c739b --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/autoban/config/manager.conf @@ -0,0 +1,9 @@ +[general] +enabled = yes +bindaddr = 127.0.0.1 +port = 5038 + +[autoban] +secret = 6003.438 +read = security +write = diff --git a/asterisk/docker-asterisk-0.9.9/src/autoban/doc/autoban.conf.sample b/asterisk/docker-asterisk-0.9.9/src/autoban/doc/autoban.conf.sample new file mode 100644 index 0000000..ad65ffd --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/autoban/doc/autoban.conf.sample @@ -0,0 +1,28 @@ +; +; autoban.conf.sample +; +; This file hold user customization of the AutoBan intrusion detection and +; prevention system. This is a php ini file. Luckily its syntax is similar to +; other asterisk conf files. "yes" and "no" have to be within quotation marks +; otherwise they will be interpreted as Boolean. The default values of the +; variables are given below. You only have to define variables with non default +; values. +; +; +;[asmanager] +;server = localhost ; here asterisk runs in same container so ami server is localhost +;port = 5038 ; should be equal to port used in manager.conf +;username = phpagi ; should be equal to username used in manager.conf, ie autoban +;secret = phpagi ; should be equal to secret used in manager.conf +; +;[autoban] +;enabled = true ; autoban is activated when autoban.conf exists and not explicitly disabled here +;maxcount = 10 ; abuse count at which IP will be jailed, ie its packets dropped +;watchtime = 20m ; time to keep IP under watch in seconds or time string eg 1d2h3m4s +;jailtime = 20m ; time to drop packets from IP in seconds or time string eg 1d2h3m4s +;repeatmult = 6 ; repeat offenders get jailtime multiplied by this factor +; +;[nftables] ; you normally don't need to mess with these variables +;cmd = nft ; +;family = inet ; +;table = autoban ; diff --git a/asterisk/docker-asterisk-0.9.9/src/autoban/doc/autoban.md b/asterisk/docker-asterisk-0.9.9/src/autoban/doc/autoban.md new file mode 100644 index 0000000..b0de9a0 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/autoban/doc/autoban.md @@ -0,0 +1,146 @@ +# AutoBan + +AutoBan is an intrusion detection and prevention system which is built in the `mlan/asterisk` container. The intrusion detection is achieved by Asterisk itself. Asterisk generates security events which AutoBan listens to on the AMI interface. When security events occurs AutoBan start to watch the source IP address. Intrusion prevention is achieved by AutoBan asking the Linux kernel firewall [nftables](https://netfilter.org/projects/nftables/) to drop packages from offending source IP addresses. + +## Operation + +Asterisk generates security events which AutoBan listens to on the AMI interface. When one of the security events; `InvalidAccountID`, `InvalidPassword`, `ChallengeResponseFailed`, or `FailedACL` occurs AutoBan start to watch the source IP address for `watchtime` seconds. If more than `maxcount` security events occurs within this time, all packages from the source IP address is dropped for `jailtime` seconds. + +When the `jailtime` expires packages are again accepted from the source IP address, but for an additional `watchtime` seconds this address is on "parole". Should a security event be detected (from this address) during the parole period it is immediately blocked again, and for a progressively longer time. This progression is configured by `repeatmult`, which determines how many times longer the address is blocked. If no security event is detected from this address during its parole time the IP is no longer being watched. + +To illustrate, first assume `jailtime=20m` and `repeatmult=6`, then the IP is blocked 20 minutes the first time, 2 hours the second, 12 hours the third, 3 days the forth and so on. + +## Configuration + +The function of AutoBan is controlled by two configuration files; `autoban.conf` and `manager.conf`. Additionally, the docker container needs extra capabilities to be able to control networking. + +| File name | Description | +| ------------ | ------------------------------------------------------------ | +| autoban.conf | Configurations which are unique to the AutoBan service | +| manager.conf | Read by the Asterisk Manager Interface (AMI), configuring both the server and client(s) | + +### Docker, runtime privileges + +AutoBan uses [nftables](https://en.wikipedia.org/wiki/Nftables) which does the actual package filtering. The container needs additional [runtime privileges](https://docs.docker.com/v17.12/engine/reference/run/#runtime-privilege-and-linux-capabilities) to be able to do that. Nftables needs the `NET_ADMIN` and `NET_RAW` capabilities to function, which you provide by adding these options to the docker run command `--cap-add=NET_ADMIN --cap-add=NET_RAW`. + +### Configuring AutoBan, autoban.conf + +AutoBan is activated if there is an `autoban.conf` file and that the parameter `enabled` within is not set to `no`. + +| Section | Key | Default | Format | Description | +| ----------- | ---------- | --------- | -------------------------------------------- | ------------------------------------------------------------ | +| [asmanager] | server | localhost | ip or fqdn | Here asterisk runs in same container so AMI server address is localhost or 127.0.0.1 | +| [asmanager] | port | 5038 | integer | AMI server port number, same as port used in manager.conf | +| [asmanager] | username | phpagi | string | AMI client name, same as section [] in manager.conf | +| [asmanager] | secret | phpagi | string | AMI client password, same as secret in manager.conf | +| [autoban] | enabled | true | boolean | AutoBan is activated when autoban.conf exists and not explicitly disabled here | +| [autoban] | maxcount | 10 | integer | Abuse count at which IP will be jailed, that is, its packets will be dropped | +| [autoban] | watchtime | 20m | string, integer followed by unit; d, h, m, s | Time to keep IP under watch in seconds or time string, example: 1d2h3m4s | +| [autoban] | jailtime | 20m | string, integer followed by unit; d, h, m, s | Time to drop packets from IP in seconds or time string example: 1d2h3m4s | +| [autoban] | repeatmult | 6 | integer or float | Repeat offenders get jailtime multiplied by this factor | + +### Configuring the AMI, manager.conf + +The AMI interface is configured in `manager.conf`.The table below does only describe to most relevant keys. Please refer to [AMI Configuration](https://wiki.asterisk.org/wiki/display/AST/AMI+v2+Specification#AMIv2Specification-AMIConfiguration), for full details. + +| Section | key | Default | Format | Description | +| ---------- | -------- | ------- | ---------- | ------------------------------------------------------------ | +| [general] | enabled | no | boolean | Enable AMI server, yes or no | +| [general] | bindaddr | 0.0.0.0 | ip address | Binds the AMI server to this IP address, for security reasons set this to; 127.0.0.1 | +| [general] | port | 5038 | integer | Port the AMI's TCP server will listen to, same as, port in autoban.conf | +| [] | | | string | Client name which AutoBan uses to authenticate with the AMI server, same as username in autoban.conf | +| [] | secret | | string | Password which AutoBan uses to authenticate with the AMI server, same as secret in autoban.conf | +| [] | read | all | string | A comma delineated list of the allowed class authorizations applied to events, for security reasons limit to; security | +| [] | write | all | string | A comma delineated list of the allowed class authorizations applied to actions, for security reasons limit to; "" | + +### Default configuration + +If the Asterisk configuration directory is empty, default configuration files will be copied there at container startup. The ones relevant here are `autoban.conf` and `manager.conf`. For security reasons it is suggested that the `secret` is changed in both files. + +`autoban.conf` + +```ini +[asmanager] +server = 127.0.0.1 +port = 5038 +username = autoban +secret = 6003.438 + +[autoban] +enabled = true +maxcount = 10 +watchtime = 20m +jailtime = 20m +repeatmult = 6 +``` +`manager.conf` + +```ini +[general] +enabled = yes +bindaddr = 127.0.0.1 +port = 5038 + +[autoban] +secret = 6003.438 +read = security +write = +``` + +## Implementation +AutoBan keeps track of which IP addresses are being watched, jailed or on parole by using the names sets and timeout constructs of [nftables](https://wiki.nftables.org/wiki-nftables/index.php/Main_Page). Timeout determines the time an element stays in the set. This mechanism is used to "automatically" keep tack of the watch, jail, and parole times. All state information is kept by nftables, so the AutoBan state can be preserved during container restarts by saving and loading the nftables configuration. + +At container startup nftables is configured by loading the file `autoban.nft` which defines the sets; watch, jail, parole, whitelist, and blacklist. Initially these sets does not contain any elements, that is, IP addresses. + +The sets; watch, jail and parole use timeout to keep track of how long the IP addresses should stay in each set. So these sets are dynamic. The sets watch and parole are only used for time keeping, so they have no rule attached. Contrarily, all packages from IP source addresses in the set jail will be dropped. + +If you want to permanently whitelist or blacklist source IP addresses, you can add them to the sets; whitelist or blacklist. Packages from source IP addresses in the set whitelist will always be accepted, whereas they will always be dropped if they are in the set blacklist. + +## Command line utility, `autoban` + +In addition to the AutoBan daemon, `autoband.php` that listens to AMI events and controls the Linux kernel firewall, there is a shell utility `autoban`, that you can use within the container, that helps with managing the NFT state. It can add, delete, white list and black list IP addresses for example. + +You can see the `autoban` help message by, from within the container, typing: + +```bash +autoban help + + DESCRIPTION + Shows an overview of the NFT state, which autoban uses to track IP adresses. + Addresses can also be added or deleted. + + USAGE + autoban [SUBCOMMAND] + If no subcommand is given use "show". + + SUBCOMMAND + add = Add to , and/or + addrs from . + del = Delete from , and/or + addrs from . + list List addrs from . + help Print this text. + show Show overview of the NFT state. + + EXAMPLES + Blacklist 77.247.110.24 and 62.210.151.21 and all addresses from jail + autoban add blacklist = 77.247.110.24 jail 62.210.151.21 + + Add all addresses in the watch set to the jail and parole sets + autoban add jail parole = watch + + Delete 37.49.230.37 and all addresses in blacklist from jail parole + autoban del jail parole = 37.49.230.37 blacklist + + Delete 45.143.220.72 from all sets + autoban del all = 45.143.220.72 + + Delete all addresses from all sets + autoban del all = all +``` + +You can watch the status of the `nftables` firewall by, from within the container, typing: + +```bash +nft list ruleset +``` diff --git a/asterisk/docker-asterisk-0.9.9/src/autoban/entry.d/50-autoban-read-nftfile b/asterisk/docker-asterisk-0.9.9/src/autoban/entry.d/50-autoban-read-nftfile new file mode 100755 index 0000000..e1083bf --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/autoban/entry.d/50-autoban-read-nftfile @@ -0,0 +1,48 @@ +#!/bin/sh +# +# 50-autoban-read-nftfile +# +# Load NFT state from file. +# + +# +# Configuration +# Note that the templates are in /etc/nftables and the actual state file is kept +# in /var/lib/nftables, which might be perceived to be counter intuitive. +# +source docker-common.sh + +DOCKER_NFT_DIR=${DOCKER_NFT_DIR-/var/lib/nftables} +DOCKER_SEED_NFT_DIR=${DOCKER_SEED_NFT_DIR-/etc/nftables} +DOCKER_NFT_FILE=${DOCKER_NFT_FILE-autoban.nft} + +# +# Make sure that we have the required directory structure in place under +# DOCKER_PERSIST_DIR. It will be missing if we mount an empty volume there. +# + +mkdir -p ${DOCKER_PERSIST_DIR}${DOCKER_NFT_DIR} + +# +# If DOCKER_NFT_DIR is empty, initialize it with files from +# DOCKER_SEED_NFT_DIR. We don't want to overwrite any files, +# but we only have "cp -u" (only copy newer) in busybox. +# The directory should be empty when we try to copy, +# so this is just an extra precaution. +# + +if [ -z "$(ls -A $DOCKER_NFT_DIR 2>/dev/null)" ]; then + dc_log 5 "Seeding nft configuration." + cp -p -u $DOCKER_SEED_NFT_DIR/$DOCKER_NFT_FILE $DOCKER_NFT_DIR +fi + +# +# If nft_file exists have NFT import it +# + +nft_file=$DOCKER_NFT_DIR/$DOCKER_NFT_FILE +if [ -f "$nft_file" ]; then + dc_log 5 "Importing $nft_file." + nft flush ruleset + nft -f ${nft_file} +fi diff --git a/asterisk/docker-asterisk-0.9.9/src/autoban/exit.d/50-autoban-write-nftfile b/asterisk/docker-asterisk-0.9.9/src/autoban/exit.d/50-autoban-write-nftfile new file mode 100755 index 0000000..c048ca9 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/autoban/exit.d/50-autoban-write-nftfile @@ -0,0 +1,29 @@ +#!/bin/sh +# +# 50-autoban-write-nftfile +# +# Save current NFT state to file. +# + +# +# Configuration +# Note that the templates are in /etc/nftables and the actual state file is kept +# in /var/lib/nftables, which might be perceived to be counter intuitive. +# +source docker-common.sh + +DOCKER_NFT_DIR=${DOCKER_NFT_DIR-/var/lib/nftables} +DOCKER_SEED_NFT_DIR=${DOCKER_SEED_NFT_DIR-/etc/nftables} +DOCKER_NFT_FILE=${DOCKER_NFT_FILE-autoban.nft} + +# +# Save current NFT state to file. Omit any "expires time-string" by using +# the option --stateless, since NFT refuse to load files with them. +# + +nft_file=$DOCKER_NFT_DIR/$DOCKER_NFT_FILE +if [ -n "$nft_file" ]; then + dc_log 5 "Saving config to $nft_file." + nft --stateless list ruleset > ${nft_file} +# nft list ruleset | sed 's/expires [[:alnum:]]*//g' > ${nft_file} +fi diff --git a/asterisk/docker-asterisk-0.9.9/src/autoban/nft/autoban.nft b/asterisk/docker-asterisk-0.9.9/src/autoban/nft/autoban.nft new file mode 100644 index 0000000..adbb11f --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/autoban/nft/autoban.nft @@ -0,0 +1,30 @@ +#!/usr/sbin/nft -f +# + +table inet autoban { + set watch { + type ipv4_addr + flags timeout + } + set jail { + type ipv4_addr + flags timeout + } + set parole { + type ipv4_addr + flags timeout + } + set blacklist { + type ipv4_addr + } + set whitelist { + type ipv4_addr + } + + chain incoming { + type filter hook input priority 0; policy accept; + ip saddr @whitelist accept + ip saddr @blacklist drop + ip saddr @jail drop + } +} diff --git a/asterisk/docker-asterisk-0.9.9/src/autoban/php/autoban.class.inc b/asterisk/docker-asterisk-0.9.9/src/autoban/php/autoban.class.inc new file mode 100644 index 0000000..6e2b067 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/autoban/php/autoban.class.inc @@ -0,0 +1,226 @@ + true, + 'maxcount' => 10, + 'watchtime' => '20m', + 'jailtime' => '20m', + 'repeatmult' => 6, + ]; + public const NFT_SETS = ['watch','jail','parole','blacklist','whitelist']; + private const TIME_MAXSEC = 99999999; + public $config; + public $debug = false; + public function __construct($config = null, array $optconfig = []) { + parent::__construct(); + if (is_string($config) !== true) { + $config = self::DEFAULT_CONF_FILE; + } + $this->config['autoban'] = self::DEFAULT_CONF_VALS; + if (file_exists($config) === true) { + $config_ini = parse_ini_file($config,true); + if (!empty($config_ini['autoban'])) + $this->config['autoban'] = array_merge($this->config['autoban'], + $config_ini['autoban']); + } else { + $this->config['autoban']['enabled'] = false; + } + foreach ($optconfig as $var => $val) { + $this->config['autoban'][$var] = $val; + } + } + /*-------------------------------------------------------------------------- + Start to count how many time we watch an IP address $ip by adding it to the + 'watch' NFT set and use the number of seconds of its timeout > 'watchtime' + as a counter. If count is > 'maxcount' add $ip to 'jail' and 'parole' NFT + sets with timeouts 'jailtime' and jailtime'+'watchtime'. If $ip is watched + during its parole immediately add it again to the 'jail' and 'parole' NFT sets + with timeouts 'repeatmult' longer than previously. + + @param string $ip eg "23.94.144.50" + @return boolean success + */ + public function book($ip) { + // if not already in jail but on parole or watch count > maxcount + // determine sentence and increment jail and parole counters + if(ip2long($ip) === false) { + trigger_error(sprintf('Got invalid IP address (%s)',$ip),E_USER_WARNING); + return false; + } + $log = null; + $watch_nft = $this->timeoutsec('watch',$ip); + $jail_nft = $this->timeoutsec('jail',$ip); + $parole_nft = $this->timeoutsec('parole',$ip); + $watch_new = $this->incrementwatch($watch_nft); + $jail_new = $this->jailsec($watch_new,$jail_nft,$parole_nft); + $parole_new = $this->parolesec($jail_new); + if ($jail_nft === false) { + if($jail_new !== false) { + $log = 'jail'; + $watch_new = false; + if ($parole_nft !== false) $this->del_addrs('parole',$ip); + } else { + $log = 'watch'; + if ($watch_nft !== false) $this->del_addrs('watch',$ip); + } + } + if ($this->add_addrs('watch',$ip,$watch_new) === false) return false; + if ($this->add_addrs('jail',$ip,$jail_new) === false) return false; + if ($this->add_addrs('parole',$ip,$parole_new) === false) return false; + switch ($log) { + case 'watch': + $this->log(sprintf('Watching %15s %-8d',$ip, + $this->countwatch($watch_new))); + break; + case 'jail': + $this->log(sprintf('Jailing %15s %8s',$ip, + $this->timestr($jail_new)),null,E_USER_WARNING); + break; + } + if ($this->save() === false) return false; + return true; + } + /*-------------------------------------------------------------------------- + Increment both watch count and watchtime, illustrated below, watchtime=20m. + $time $count $time + false 1 20m1s + 20m1s 2 20m2s + 20m2s 3 20m3s + 20m3s 4 20m4s + 20m4s 5 20m5s + + @param mixed $time integer time in seconds or boolean false + @return integer time + 1 + */ + private function incrementwatch($time) { + if($time === false) { + return $this->configsec('watchtime') + 1; + } else { + return $time + 1; + } + } + /*-------------------------------------------------------------------------- + @param integer $time integer time in seconds + @return integer count + */ + private function countwatch($time) { + return $time - $this->configsec('watchtime'); + } + /*-------------------------------------------------------------------------- + Compute sentencing time which is last jailtime times repeatmult if in parole. + Sentencing is jailtime if first time offender watch count >= maxcount. + Return false if already in jail or watch count < maxcount. + + @param mixed $watchtime integer time in seconds or boolean false + @param mixed $jailtime integer time in seconds or boolean false + @param mixed $paroletime integer time in seconds or boolean false + @return mixed integer sentence time in seconds or boolean false + */ + private function jailsec($watchtime,$jailtime,$paroletime) { + if ($jailtime !== false) return false; + if ($paroletime !== false) { + $jailt = max($this->configsec('jailtime'), + $paroletime - $this->configsec('watchtime')); + return $jailt * $this->config['autoban']['repeatmult']; + } elseif (($watchtime !== false) && + ($watchtime - $this->configsec('watchtime') >= + $this->config['autoban']['maxcount'])) { + return $sentence = $this->configsec('jailtime'); + } + return false; + } + /*-------------------------------------------------------------------------- + Compute probation time = sentence time + watchtime. Also make sure both + probation and sentence times are sane. + + @param mixed &$sentence integer time in seconds or boolean false + @return mixed integer probation time in seconds or boolean false + */ + private function parolesec(&$sentence) { + if ($sentence === false) return false; + $watchtime = $this->configsec('watchtime'); + if ($watchtime > 0.5*self::TIME_MAXSEC) $watchtime = 0.5*self::TIME_MAXSEC; + $parole = $sentence + $watchtime; + if ($parole > self::TIME_MAXSEC) { + $parole = self::TIME_MAXSEC; + $sentence = $parole - $watchtime; + } + $sentence = round($sentence); + return round($parole); + } + /*-------------------------------------------------------------------------- + @param string $set eg "jail" + @param string $ip eg "23.94.144.50" + @return mixed time integer seconds or boolean false + */ + public function timeoutsec($set,$ip) { + return $this->str2sec($this->get_timeout($set,$ip)); + } + /*-------------------------------------------------------------------------- + @param string $set eg "jail" + @return mixed time integer seconds or boolean false + */ + public function configtime($set) { + switch ($set) { + case 'watch': + $sec = $this->configsec('watchtime'); + break; + case 'jail': + $sec = $this->configsec('jailtime'); + break; + case 'parole': + $sec = $this->configsec('jailtime') + $this->configsec('watchtime'); + break; + default: + $sec = null; + } + return $this->sec2str($sec); + } + /*-------------------------------------------------------------------------- + Convert config times in sting format to seconds eg "20m" to 1200 + @param string $param eg, "watchtime" + @return integer $seconds + */ + public function configsec($param) { + $time = $this->config['autoban'][$param]; + if(!is_numeric($time)) $time = $this->str2sec($time); + return $time; + } + /*-------------------------------------------------------------------------- + @param string $message eg "Jailing 23.94.144.50" + @param mixed $error eg 404 + @param integer $level eg E_USER_WARNING + @return void + */ + public function log($message, $error = [], $level = E_USER_NOTICE) { + if (isset($error[0])) { + $message = $message.' error: '.$error[0]; + } else { + $nr_watch = count($this->list('watch')); + $nr_jail = count($this->list('jail')); + $message = sprintf('%s (watch %-3d jail %-3d)', + $message,$nr_watch,$nr_jail); + } + trigger_error($message, $level); + } +} +?> diff --git a/asterisk/docker-asterisk-0.9.9/src/autoban/php/autoban.php b/asterisk/docker-asterisk-0.9.9/src/autoban/php/autoban.php new file mode 100755 index 0000000..cf54e49 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/autoban/php/autoban.php @@ -0,0 +1,177 @@ +#!/usr/bin/env php + = Add to , and/or + addrs from . + del = Delete from , and/or + addrs from . + list List addrs from . + help Print this text. + show Show overview of the NFT state. + + EXAMPLES + Blacklist 77.247.110.24 and 62.210.151.21 and all addresses from jail + autoban add blacklist = 77.247.110.24 jail 62.210.151.21 + + Add all addresses in the watch set to the jail and parole sets + autoban add jail parole = watch + + Delete 37.49.230.37 and all addresses in blacklist from jail parole + autoban del jail parole = 37.49.230.37 blacklist + + Delete 45.143.220.72 from all sets + autoban del all = 45.143.220.72 + + Delete all addresses from all sets + autoban del all = all + + +HELP_MESSAGE; + +/*------------------------------------------------------------------------------ + Initiate logging and load dependencies. +*/ +openlog("autoban", LOG_PID | LOG_PERROR, LOG_LOCAL0); +require_once 'error.inc'; +require_once 'autoban.class.inc'; + +/*------------------------------------------------------------------------------ + Create class objects and set log level. +*/ +$ban = new Autoban(); + +/*-------------------------------------------------------------------------- +Add elements $addr to NFT set $set +@param array of strings $args eg ["blacklist", "=", "77.247.110.24", "jail"] +@return boolean false if unable to add element else true +*/ +function add($args) { + global $ban; + parse($args,$dargs,$sargs,'blacklist'); + foreach ($dargs as $dset) { + $timeout = $ban->configtime($dset); + $assume_ssets = array_intersect($sargs,Autoban::NFT_SETS); + $assume_saddrs = array_diff($sargs,Autoban::NFT_SETS); + foreach ($assume_ssets as $sset) { + $saddrs = array_keys($ban->list($sset)); + $ban->add_addrs($dset, $saddrs, $timeout); + } + $ban->add_addrs($dset, $assume_saddrs, $timeout, true); + } + $ban->save(); +} + +/*-------------------------------------------------------------------------- +Delete elements $args from NFT sets $sets +@param array of strings $args eg ["blacklist", "=", "77.247.110.24", "jail"] +@return boolean false if unable to delete element else true +*/ +function del($args) { + global $ban; + parse($args,$dargs,$sargs,'all'); + if (array_search('all', $dargs) !== false) $dargs = Autoban::NFT_SETS; + foreach ($dargs as $dset) { + $assume_ssets = array_intersect($sargs,Autoban::NFT_SETS); + foreach ($assume_ssets as $sset) { + $saddrs = array_keys($ban->list($sset)); + $ban->del_addrs($dset, $saddrs); + } + $assume_saddrs = array_diff($sargs,Autoban::NFT_SETS); + $ban->del_addrs($dset, $assume_saddrs); + } + $ban->save(); +} + +/*-------------------------------------------------------------------------- +List elements in NFT sets $sets +@param array of strings $args eg ["blacklist", "jail"] +@return void +*/ +function ls($args) { + global $ban; + if (empty($args) || array_search('all', $args) !== false) + $args = Autoban::NFT_SETS; + foreach ($args as $set) + if (count($args) === 1) + printf("%s\n", implode(' ',array_keys($ban->list($set)))); + else + printf("%s: %s\n", $set, implode(' ',array_keys($ban->list($set)))); +} + +/*-------------------------------------------------------------------------- +Separates argument in to $dargs and $sargs using the separator +@param array of strings $args eg ["blacklist", "=", "77.247.110.24", "jail"] +@param array of strings $dargs eg ["blacklist"] +@param array of strings $sargs eg ["77.247.110.24", "jail"] +@return void +*/ +function parse($args, &$dargs, &$sargs, $default = 'all', $separators = ':+-=') { + $left = []; $right = []; + foreach ($args as $arg) { + if (strlen($arg) === 1 && strstr($separators, $arg) !== false) { + $mid = $arg; + } else { + if (empty($mid)) { + array_push($left, $arg); + } else { + array_push($right, $arg); + } + } + } + if (empty($right)) { + $dargs = [$default]; + $sargs = $left; + } else { + $dargs = $left; + $sargs = $right; + } +} +/*------------------------------------------------------------------------------ + Start code execution. + Scrape off command and sub-command and pass the rest of the arguments. +*/ +#$ban->debug = true; +$subcmd=@$argv[1]; +unset($argv[0],$argv[1]); +#if(!empty($subcmd)) +# trigger_error(sprintf('Running %s %s', $subcmd, implode(' ',$argv)), +# E_USER_NOTICE); +switch (@$subcmd) { + case 'add': + case 'a': + add(@$argv); + break; + case 'delete': + case 'del': + case 'd': + del(@$argv); + break; + case 'list': + case 'ls': + case 'l': + ls(@$argv); + break; + case 'show': + case 's': + case '': + $ban->show(); + break; + case 'help': + default: + print $HELP_MESSAGE; + break; +} +?> diff --git a/asterisk/docker-asterisk-0.9.9/src/autoban/php/autoband.php b/asterisk/docker-asterisk-0.9.9/src/autoban/php/autoband.php new file mode 100755 index 0000000..5b1a323 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/autoban/php/autoband.php @@ -0,0 +1,77 @@ +#!/usr/bin/env php +book($ip); + } + } +} + +/*------------------------------------------------------------------------------ + Create class objects and set log level. +*/ +$ban = new \Autoban('/etc/asterisk/autoban.conf'); +$ami = new \PHPAMI\Ami('/etc/asterisk/autoban.conf'); +$ami->setLogLevel(2); + +/*------------------------------------------------------------------------------ + Register the AMI event handlers to their corresponding events. +*/ +$ami->addEventHandler('FailedACL', 'eventAbuse'); +$ami->addEventHandler('InvalidAccountID', 'eventAbuse'); +$ami->addEventHandler('ChallengeResponseFailed', 'eventAbuse'); +$ami->addEventHandler('InvalidPassword', 'eventAbuse'); + +/*------------------------------------------------------------------------------ + Start code execution. + Wait 1s allowing Asterisk time to setup the Asterisk Management Interface (AMI). + If autoban is activated try to connect to the AMI. If successful, start + listening for events indefinitely. If connection fails, retry to connect. + If autoban is deactivated stay in an infinite loop instead of exiting. + Otherwise the system supervisor will relentlessly just try to restart us. +*/ +$wait_init = 2; +$wait_extra = 58; +$wait_off = 3600; +if ($ban->config['autoban']['enabled']) { + while(true) { + sleep($wait_init); + if ($ami->connect()) { + trigger_error('Activated and connected to AMI',E_USER_NOTICE); + $ami->waitResponse(); // listen for events until connection fails + $ami->disconnect(); + } else { + trigger_error('Unable to connect to AMI',E_USER_ERROR); + sleep($wait_extra); + } + } +} else { + trigger_error('Disabled! Activate autoban using conf file '. + '(/etc/asterisk/autoban.conf)',E_USER_NOTICE); + while(true) { sleep($wait_off); } +} + + +/*------------------------------------------------------------------------------ + We will never come here. +*/ +?> diff --git a/asterisk/docker-asterisk-0.9.9/src/autoban/php/nft.class.inc b/asterisk/docker-asterisk-0.9.9/src/autoban/php/nft.class.inc new file mode 100644 index 0000000..655e2ec --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/autoban/php/nft.class.inc @@ -0,0 +1,327 @@ + 'nft', + 'opt' => '--stateless', + 'sub' => null, + 'family' => 'inet', + 'table' => 'autoban', + 'chain' => null, + 'set' => null, + 'val' => null, + 'stderr' => '2>&1', + ]; + public const NFT_SETS = ['watch','jail','parole','blacklist','whitelist']; + private const TIME_UNITS = ['d' => 86400, 'h' => 3600, 'm' => 60, 's' => 1]; + private const SHOW_MARK = 'X'; + private const SHOW_ID = 'addr'; + private const NFT_DIR = '/var/lib/nftables'; + private const NFT_FILE = 'autoban.nft'; + private $nft_statefile; + public $debug = false; + /*-------------------------------------------------------------------------- + Constructor + @return void + */ + public function __construct() { + $nft_dir = (getenv('DOCKER_NFT_DIR') !== false) ? + getenv('DOCKER_NFT_DIR') : self::NFT_DIR; + $nft_file = (getenv('DOCKER_NFT_FILE') !== false) ? + getenv('DOCKER_NFT_FILE') : self::NFT_FILE; + $this->nft_statefile = $nft_dir.'/'.$nft_file; + } + /*-------------------------------------------------------------------------- + Add element $addr to NFT set $set with timeout $timeout seconds + @param string $set eg "jail" + @param string $addr eg "23.94.144.50" + @param mixed $timeout int seconds eg 1200 or boolean false + @return boolean false if unable to add element else true + */ + public function add($set, $addr, $timeout = null, $check = false) { + if ($check && !$this->is_addr($addr)) return false; + if ($this->add_addrs($set,$addr,$timeout) === false) return false; + if ($this->save() === false) return false; + return true; + } + /*-------------------------------------------------------------------------- + Delete element $addr from NFT set $set + @param string $set eg "jail" + @param string $addr eg "23.94.144.50" + @return mixed boolean false if unable to del element else true + */ + public function del($set, $addr = null, $check = false) { + if ($check) if (!$this->is_addr($addr)) return false; + if ($this->del_addrs($set,$addr) === false) return false; + if ($this->save() === false) return false; + return true; + } + /*-------------------------------------------------------------------------- + Get array of all addr in set $set. + @param string $set eg "jail" + @return array [string addr => string time, ...] or [] is set is empty + */ + public function list($set) { + $return = $this->list_addr($set); + if ($return === false) return []; + return $this->array_elem($return); + } + /*-------------------------------------------------------------------------- + Get timeout for $addr from NFT set $set + @param string $set eg "jail" + @param string $addr eg "23.94.144.50" + @return mixed exec return string or boolean false if unable to get timeout + */ + public function get_timeout($set,$addr) { + $timeout = $this->array_elem($this->get_addr($set,$addr)); + if (!empty($timeout)) return array_values($timeout)[0]; + return false; + } + /*-------------------------------------------------------------------------- + Add element $addr to NFT set $set with timeout $timeout seconds + @param string $set eg "jail" + @param mixed $addrs string eg "23.94.144.50" or array ["23.94.144.50",...] or null or false + @param mixed $timeout int seconds eg 1200 or boolean false + @return mixed exec return string or boolean false if unable to add elements + */ + public function add_addrs($set,$addrs,$timeout = null) { + if (empty($addrs) || $timeout === false) return true; + $suffix = (empty($timeout)) ? '' : ' timeout '.$this->timestr($timeout); + if(is_array($addrs)) { + $addrs = array_map(function($a) use ($suffix) { return $a.$suffix; }, $addrs); + $val = implode(', ', $addrs); + } else { + $val = $addrs.$suffix; + } + $args = ['sub'=>'add element', 'set'=>$set, 'val'=>'{'.$val.'}']; + return $this->exec($args); + } + /*-------------------------------------------------------------------------- + Delete element $addr from NFT set $set + @param string $set eg "jail" + @param mixed $addrs string eg "23.94.144.50" or array ["23.94.144.50","all",...] or null + @return mixed exec return string or boolean false if unable to del elements + */ + public function del_addrs($set, $addrs = null) { + if (empty($addrs)) return true; + $given_addrs = (is_array($addrs)) ? $addrs : [$addrs]; + if (array_search('all', $given_addrs) !== false) { + $args = ['sub'=>'flush set','set'=>$set]; + } else { + $valid_addrs = array_keys($this->list($set)); + $the_addrs = array_intersect($given_addrs, $valid_addrs); + if (empty($the_addrs)) return true; + $val = implode(', ', $the_addrs); + $args = ['sub'=>'delete element','set'=>$set,'val'=>'{'.$val.'}']; + } + return $this->exec($args); + } + /*-------------------------------------------------------------------------- + Get element $addr from NFT set $set + @param string $set eg "jail" + @param string $addr eg "23.94.144.50" + @return mixed exec return string or boolean false if unable to del element + */ + public function get_addr($set,$addr) { + if (empty($addr)) return true; + $args = ['sub'=>'get element','set'=>$set,'val'=>'{'.$addr.'}']; + return $this->exec($args, false); + } + /*-------------------------------------------------------------------------- + List elements in NFT set $set + @param string $set eg "jail" + @return mixed exec return string or boolean false if unable to del element + */ + public function list_addr($set) { + $args = ['sub'=>'list set','set'=>$set]; + return $this->exec($args); + } + /*-------------------------------------------------------------------------- + NFT returns elements = { 23.94.144.50 timeout 40m, ...} + We stuff this into $this->timeout[$set] = [string addr => string time, ...]. + + @param array $return strings return from calling NFT + @return array [string addr => string time, ...] or [] is set is empty + */ + public function array_elem($return) { + if ($return === false) return []; + preg_match('/flags timeout/', implode($return), $hastimeout); + preg_match('/elements = {([^}]+)}/', implode($return), $matches); + if (empty($matches[1])) return []; + $elements = preg_split('/,/', $matches[1]); + $timeout = []; + foreach ($elements as $element) { + if (empty($hastimeout)) { + $timeout += [trim($element) => Self::SHOW_MARK]; + } else { + $addrntime = explode(' timeout ',$element); + $timeout += [trim($addrntime[0]) => trim($addrntime[1])]; + } + } + return $timeout; + } + /*-------------------------------------------------------------------------- + Save NFT state to file. Rename the old state file by appending "~" to the + filename before saving the NFT state. + @return mixed state string or boolean false if unsuccessful + */ + public function save() { + $args = ['sub'=>'list ruleset', 'family'=>null, 'table'=>null]; + $return = $this->exec($args); + if ($return === false) return false; + @rename($this->nft_statefile, $this->nft_statefile.'~'); + if (file_put_contents($this->nft_statefile,implode(PHP_EOL, $return)) + === false) { + $this->log('('.$this->nft_statefile.')', [ 'Unable to write' ], + E_USER_WARNING); + return false; + } + return $return; + } + /*-------------------------------------------------------------------------- + @param array $args NFT cli arguments eg ['sub'=>'list set','set'=>'jail'] + @return mixed NFT return string or boolean false if error status + */ + private function exec($args, $logerror = true) { + $exec_array = array_merge(self::NFT_SYNTAX,$args); + $exec_string = implode(' ',$exec_array); + $this->debug($exec_string); + exec($exec_string,$return,$status); + if ($status === 0) { + return $return; + } else { + if ($logerror) { + $this->log('('.$exec_array['sub'].')', $return, E_USER_WARNING); + $this->debug($exec_string); + } + return false; + } + } + /*-------------------------------------------------------------------------- + @param mixed $time string eg, "1d9h40m1s" integer 1200 or null + @return string $time eg, "1d9h40m1s" or null or boolean false + */ + public function timestr($time) { + if (empty($time)) return $time; + if (is_numeric($time)) return $this->sec2str($time); + if ($this->str2sec($time) === false) { + return false;; + } else { + return $time; + } + } + /*-------------------------------------------------------------------------- + @param string $time eg, "1d9h40m1s" + @return mixed $seconds int seconds or boolean false + */ + public function str2sec($time) { + if ($time === false || $time === null) return $time; + preg_match_all('/(\d+)([dhms])/',$time,$matches); + if (empty($matches[0])) return false; + $unitvalue = array_combine($matches[2],$matches[1]); + $seconds = 0; + foreach ($unitvalue as $unit => $value) { + $seconds += self::TIME_UNITS[$unit] * $value; + } + return $seconds; + } + /*-------------------------------------------------------------------------- + @param integer $seconds + @return string $time eg, "1d9h40m1s" + */ + public function sec2str($seconds) { + if ($seconds === false || $seconds === null) return $seconds; + $time = ""; + foreach (self::TIME_UNITS as $unit => $scale) { + $number = floor($seconds / $scale); + if ($number > 0) { + $time .= sprintf('%d%s',$number,$unit); + $seconds = $seconds % $scale; + } + } + return $time; + } + /*-------------------------------------------------------------------------- + @param string $addr eg "23.94.144.50" + @return boolean + */ + public function is_addr($addr) { + if (ip2long($addr) === false) { + trigger_error(sprintf('Got invalid IP address (%s)', + $addr),E_USER_WARNING); + return false; + } else return true; + } + /*-------------------------------------------------------------------------- + @param mixed $time string eg, "1d9h40m1s" + @return boolean + */ + public function is_timestr($timeout) { + if ($this->timestr($timeout) === false) { + trigger_error(sprintf('Got invalid timeout value (%s)', + $timeout),E_USER_WARNING); + return false; + } else return true; + } + /*-------------------------------------------------------------------------- + @param string $message eg "Jailing 23.94.144.50" + @param mixed $error eg 404 + @param integer $level eg E_USER_WARNING + @return void + */ + public function log($message, $error = [], $level = E_USER_NOTICE) { + if (isset($error[0])) { + $message = $message.' error: '.$error[0]; + } + trigger_error($message, $level); + } + /*-------------------------------------------------------------------------- + print table with headers: addr watch jail parole blacklist whitelist + @return void + */ + public function show() { + $db = []; + $id = self::SHOW_ID; + $headers = array_merge([$id],self::NFT_SETS); + $sets_num = count(self::NFT_SETS); + $form = "%15s".str_repeat("%13s", $sets_num)."\n"; + foreach (self::NFT_SETS as $set) { + $elems = $this->list($set); + if (!empty($elems)) foreach ($elems as $addr => $time) { + $db_index = array_search($addr, array_column($db, $id)); + if ($db_index === false) { + $db_index = -1 + array_push($db, array_merge([$id => $addr], + array_combine(self::NFT_SETS, + array_fill(0,$sets_num,null)))); + } + $db[$db_index][$set] = $time; + } + } + usort($db, function($a,$b) use ($id) { + return ip2long($a[$id]) <=> ip2long($b[$id]); + }); + $db_sums = array_map(function($head) use ($db) { + return count(array_filter(array_column($db, $head))); + }, $headers); + vprintf($form,$headers); + if (!empty($db)) foreach ($db as $elem) { + vprintf($form,array_values($elem)); + } + vprintf($form,$db_sums); + + } + /*-------------------------------------------------------------------------- + Print variable if $debug or $this->debug is true + @param mixed $var + @param boolean $debug + @return void + */ + public function debug($var, $debug = false) { + if($debug || $this->debug) { + var_dump($var); + } + } +} +?> diff --git a/asterisk/docker-asterisk-0.9.9/src/common/php/error.inc b/asterisk/docker-asterisk-0.9.9/src/common/php/error.inc new file mode 100644 index 0000000..f2a595a --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/common/php/error.inc @@ -0,0 +1,36 @@ + diff --git a/asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-common.sh b/asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-common.sh new file mode 100644 index 0000000..229b70b --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-common.sh @@ -0,0 +1,146 @@ +#!/bin/sh +# +# docker-common.sh +# +# Defines common functions. Source this file from other scripts. +# +DOCKER_LOGLEVEL=${DOCKER_LOGLEVEL-5} +DOCKER_LOGENTRY=${DOCKER_LOGENTRY-docker-entrypoint.sh} +DOCKER_LOGUSAGE=${DOCKER_LOGUSAGE-usage} + +# +# Write messages to console if interactive or syslog if not. +# Usage: inform priority message +# The priority may be specified numerically or as a facility.level pair. +# Example user.notice, or 1.6 level is one of: +# 0|emerg|1|alert|2|crit|3|err|4|warning|5|notice|6|info|7|debug +# +dc_log() { + local script=$(basename $0) + local stamp="$(dc_log_stamp)" + local prio=$1 + local level=${prio#*.} + local logtag="${script}[${$}]" + local ttytag="$(dc_log_stamp)$(dc_log_tag $level $logtag):" + shift + # Assume interactive if we have stdout open and print usage message if needed. + if [ -t 1 ]; then + echo "$@" + case "$level" in + 0|emerg|1|alert|2|crit|3|err) $DOCKER_LOGUSAGE 2>/dev/null ;; + esac + else + # If we have /dev/log socket send message to logger otherwise to stdout. + if [ -S /dev/log ]; then + logger -t "$logtag" -p "$prio" "$@" + else + if dc_log_level "$level"; then + echo "$ttytag $@" + fi + fi + fi +} + +# +# Color log output. Used if the syslogd daemon is not running. +# +dc_log_tag() { + local level=$1 + local string=$2 + local c l + case $level in + 0|emerg) c=91; l=EMERG ;; + 1|alert) c=91; l=ALERT ;; + 2|crit) c=91; l=CRIT ;; + 3|err) c=91; l=ERROR ;; + 4|warning) c=93; l=WARN ;; + 5|notice) c=92; l=NOTE ;; + 6|info) c=92; l=INFO ;; + 7|debug) c=92; l=DEBUG ;; + esac + printf "\e[%sm%s %s\e[0m\n" $c $string $l +} + +# +# Use $DOCKER_LOGLEVEL during image build phase. Assume we are in build phase if +# $DOCKER_LOGENTRY is not running. +# +dc_log_level() { + local level=$1 + if pidof $DOCKER_LOGENTRY >/dev/null; then + [ "$level" -le "$SYSLOG_LEVEL" ] + else + [ "$level" -le "$DOCKER_LOGLEVEL" ] + fi +} + +# +# Don't add time stamp during image build phase. Assume we are in build phase if +# $DOCKER_LOGENTRY is not running. +# +dc_log_stamp() { + if grep -q $DOCKER_LOGENTRY /proc/1/cmdline; then + date +'%b %e %X ' + fi +} + +# +# Tests if command is in the path +# +dc_is_command() { [ -x "$(command -v $1)" ] ;} + +# +# Tests if pkgs are installed +# +dc_is_installed() { + if dc_is_command apk; then + ver_cmd="apk -e info" + elif dc_is_command dpkg; then + ver_cmd="dpkg -s" + else + dc_log 5 "No package manager found among: apk dpkg" + fi + for cmd in $@; do + $ver_cmd $cmd > /dev/null 2>&1 || return 1 + done +} + +# +# Update loglevel +# +dc_update_loglevel() { + loglevel=${1-$SYSLOG_LEVEL} + if [ -n "$loglevel" ]; then + dc_log 5 "Setting syslogd level=$loglevel." + docker-service.sh "syslogd -nO- -l$loglevel $SYSLOG_OPTIONS" + [ -n "$DOCKER_RUNFUNC" ] && sv restart syslogd + fi +} + +# +# Print package versions +# +dc_pkg_versions() { + local pkgs="$@" + local len=$(echo $pkgs | tr " " "\n" | wc -L) + local ver ver_cmd sed_flt + local os=$(sed -rn 's/PRETTY_NAME="(.*)"/\1/p' /etc/os-release) + local kern=$(uname -r) + local host=$(uname -n) + dc_log 5 $host $os $kern + if dc_is_command apk; then + ver_cmd="apk info -s" + sed_flt="s/.*-(.*)-.*/\1/p" + elif dc_is_command dpkg; then + ver_cmd="dpkg -s" + sed_flt="s/Version: ([[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+).*/\1/p" + else + dc_log 5 "No package manager found among: apk dpkg" + fi + for pkg in $pkgs; do + ver=$($ver_cmd $pkg 2> /dev/null | sed -rn "$sed_flt") + if [ -n "$ver" ]; then + printf "\t%-${len}s\t%s\n" $pkg $ver + fi + done +} diff --git a/asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-config.sh b/asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-config.sh new file mode 100644 index 0000000..367b890 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-config.sh @@ -0,0 +1,280 @@ +#!/bin/sh +# +# docker-config.sh +# +# Defines common functions. Source this file from other scripts. +# +# Defined in Dockerfile: +# DOCKER_UNLOCK_FILE +# +HOSTNAME=${HOSTNAME-$(hostname)} +DOMAIN=${HOSTNAME#*.} +TLS_KEYBITS=${TLS_KEYBITS-2048} +TLS_CERTDAYS=${TLS_CERTDAYS-30} +DOCKER_CRONTAB_FILE=${DOCKER_CRONTAB_FILE-/etc/crontab} +DOCKER_CRONTAB_ENV=${DOCKER_CRONTAB_ENV-CRONTAB_ENTRY} + +# +# general file manipulation commands, used both during build and run time +# + +_escape() { echo "$@" | sed 's|/|\\\/|g' | sed 's|;|\\\;|g' | sed 's|\$|\\\$|g' | sed "s/""'""/\\\x27/g" ;} + +dc_modify() { + local cfg_file=$1 + shift + local lhs="$1" + shift + local eq= + local rhs= + if [ "$1" = "=" ]; then + eq="$1" + shift + rhs="$(_escape $@)" + else + rhs="$(_escape $@)" + fi + dc_log 7 's/.*('"$lhs"'\s*'"$eq"'\s*)[^#]+(.*)/\1'"$rhs"' \2/g' $cfg_file + sed -ri 's/.*('"$lhs"'\s*'"$eq"'\s*)[^#]+(.*)/\1'"$rhs"' \2/g' $cfg_file +} + +dc_replace() { + local cfg_file=$1 + local old="$(_escape $2)" + local new="$(_escape $3)" + dc_log 7 's/'"$old"'/'"$new"'/g' $cfg_file + sed -i 's/'"$old"'/'"$new"'/g' $cfg_file +} + +dc_addafter() { + local cfg_file=$1 + local startline="$(_escape $2)" + local new="$(_escape $3)" + dc_log 7 '/'"$startline"'/!{p;d;}; $!N;s/\n\s*$/\n'"$new"'\n/g' $cfg_file + sed -i '/'"$startline"'/!{p;d;}; $!N;s/\n\s*$/\n'"$new"'\n/g' $cfg_file +} + +dc_comment() { + local cfg_file=$1 + local string="$2" + dc_log 7 '/^'"$string"'/s/^/#/g' $cfg_file + sed -i '/^'"$string"'/s/^/#/g' $cfg_file +} + +dc_uncommentsection() { + local cfg_file=$1 + local startline="$(_escape $2)" + dc_log 7 '/^'"$startline"'$/,/^\s*$/s/^#*//g' $cfg_file + sed -i '/^'"$startline"'$/,/^\s*$/s/^#*//g' $cfg_file +} + +dc_removeline() { + local cfg_file=$1 + local string="$2" + dc_log 7 '/'"$string"'.*/d' $cfg_file + sed -i '/'"$string"'.*/d' $cfg_file +} + +dc_uniquelines() { + local cfg_file=$1 + dc_log 7 '$!N; /^(.*)\n\1$/!P; D' $cfg_file + sed -ri '$!N; /^(.*)\n\1$/!P; D' $cfg_file +} + + +# +# Persist dirs +# + +# +# Make sure that we have the required directory structure in place under +# DOCKER_PERSIST_DIR. +# +dc_persist_mkdirs() { + local dirs=$@ + for dir in $dirs; do + mkdir -p ${DOCKER_PERSIST_DIR}${dir} + done +} + +# +# Make sure that we have the required directory structure in place under +# DOCKER_PERSIST_DIR. +# +dc_persist_dirs() { + local srcdirs="$@" + local dstdir + if [ -n "$DOCKER_PERSIST_DIR" ]; then + for srcdir in $srcdirs; do + mkdir -p "$srcdir" + dstdir="${DOCKER_PERSIST_DIR}${srcdir}" + mkdir -p "$(dirname $dstdir)" + mv -f "$srcdir" "$(dirname $dstdir)" + ln -sf "$dstdir" "$srcdir" + dc_log 5 "Moving $srcdir to $dstdir" + done + fi +} + +# +# mv dir to persist location and leave a link to it +# +dc_persist_mvdirs() { + local srcdirs="$@" + if [ -n "$DOCKER_PERSIST_DIR" ]; then + for srcdir in $srcdirs; do + if [ -e "$srcdir" ]; then + local dstdir="${DOCKER_PERSIST_DIR}${srcdir}" + local dsthome="$(dirname $dstdir)" + if [ ! -d "$dstdir" ]; then + dc_log 5 "Moving $srcdir to $dstdir" + mkdir -p "$dsthome" + mv "$srcdir" "$dsthome" + ln -sf "$dstdir" "$srcdir" + else + dc_log 4 "$srcdir already moved to $dstdir" + fi + else + dc_log 4 "Cannot find $srcdir" + fi + done + fi +} + +# +# Conditionally change owner of files. +# -a all +# -r readable +# -w writable +# -x executable +# +dc_cond_chown() { + dc_log 7 "Called with args: $@" + OPTIND=1 + local find_opts="! -perm -404" + while getopts ":arwx" opts; do + case "${opts}" in + a) find_opts="";; + r) find_opts="! -perm -404";; + w) find_opts="! -perm -606";; + x) find_opts="! -perm -505";; + esac + done + shift $((OPTIND -1)) + local user=$1 + shift + if id $user > /dev/null 2>&1; then + for dir in $@; do + if [ -n "$(find $dir ! -user $user $find_opts -print -exec chown -h $user: {} \;)" ]; then + dc_log 5 "Changed owner to $user for some files in $dir" + fi + done + else + dc_log 3 "User $user is unknown." + fi +} + +# +# Append entry if it is not already there. If mode is -i then append before last line. +# +dc_cond_append() { + local mode filename lineraw lineesc + case $1 in + -i) mode=i; shift;; + -a) mode=a; shift;; + *) mode=a;; + esac + filename=$1 + shift + lineraw=$@ + lineesc="$(echo $lineraw | sed 's/[\";/*]/\\&/g')" + if [ -e "$filename" ]; then + if [ -z "$(sed -n '/'"$lineesc"'/p' $filename)" ]; then + dc_log 7 "dc_cond_append append: $mode $filename $lineraw" + case $mode in + a) echo "$lineraw" >> $filename;; + i) sed -i "$ i\\$lineesc" $filename;; + esac + else + dc_log 4 "Avoiding duplication: $filename $lineraw" + fi + else + dc_log 7 "dc_cond_append create: $mode $filename $lineraw" + echo "$lineraw" >> $filename + fi +} + +dc_cpfile() { + local suffix=$1 + shift + local cfs=$@ + for cf in $cfs; do + cp "$cf" "$cf.$suffix" + done +} + +dc_mvfile() { + local suffix=$1 + shift + local cfs=$@ + for cf in $cfs; do + mv "$cf" "$cf.$suffix" + done +} + +# +# Prune PID files +# +dc_prune_pidfiles() { + local dirs=$@ + for dir in $dirs; do + if [ -n "$(find -H $dir -type f -name "*.pid" -exec rm {} \; 2>/dev/null)" ]; then + dc_log 5 "Removed orphan pid files in $dir" + fi + done +} + +# +# Setup crontab entries +# +dc_crontab_entries() { + local entries="$(eval echo \${!$DOCKER_CRONTAB_ENV*})" + for entry in $entries; do + [ -z "${changed+x}" ] && local changed= && sed -i '/^\s*[0-9*]/d' $DOCKER_CRONTAB_FILE + echo "${!entry}" >> $DOCKER_CRONTAB_FILE + dc_log 5 "Added entry ${!entry} in $DOCKER_CRONTAB_FILE" + done +} + +# +# TLS/SSL Certificates [openssl] +# +dc_tls_setup_selfsigned_cert() { + local cert=$1 + local key=$2 + if ([ ! -s $cert ] || [ ! -s $key ]); then + dc_log 5 "Setup self-signed TLS certificate for host $HOSTNAME" + openssl genrsa -out $key $TLS_KEYBITS + openssl req -x509 -utf8 -new -batch -subj "/CN=$HOSTNAME" \ + -days $TLS_CERTDAYS -key $key -out $cert + fi +} + +# +# Configuration Lock +# +dc_lock_config() { + if [ -f "$DOCKER_UNLOCK_FILE" ]; then + rm $DOCKER_UNLOCK_FILE + dc_log 5 "Removing unlock file, locking the configuration." + elif [ -n "$FORCE_CONFIG" ]; then + dc_log 5 "Configuration update was forced, since we got FORCE_CONFIG=$FORCE_CONFIG" + else + dc_log 5 "No unlock file found, so not touching configuration." + fi +} + +# +# true if there is no unlock file or FORCE_CONFIG is not empty +# +dc_is_unlocked() { [ -f "$DOCKER_UNLOCK_FILE" ] || [ -n "$FORCE_CONFIG" ] ;} diff --git a/asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-entrypoint.sh b/asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-entrypoint.sh new file mode 100755 index 0000000..ffc4116 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-entrypoint.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env sh +# set -x +# +# This script need to run as PID 1 allowing it to receive signals from docker +# +# Usage: add the folowing lines in Dockerfile +# ENTRYPOINT ["docker-entrypoint.sh"] +# CMD runsvdir -P ${SVDIR} +# + +# +# Variables +# +DOCKER_ENTRY_DIR=${DOCKER_ENTRY_DIR-/etc/docker/entry.d} +DOCKER_EXIT_DIR=${DOCKER_EXIT_DIR-/etc/docker/exit.d} +SVDIR=${SVDIR-/etc/service} + +# +# Source common functions. +# +. docker-common.sh +. docker-config.sh + +# +# Functions +# + +# +# run_parts dir +# Read and execute commands from files in the _current_ shell environment +# +run_parts() { + for file in $(find $1 -type f -executable 2>/dev/null|sort); do + dc_log 7 run_parts: executing $file + . $file + done +} + +# +# If the service is running, send it the TERM signal, and the CONT signal. +# If both files ./run and ./finish exits, execute ./finish. +# After it stops, do not restart the service. +# +sv_down() { sv down ${SVDIR}/* ;} + +# +# SIGTERM handler +# docker stop first sends SIGTERM, and after a grace period, SIGKILL. +# use exit code 143 = 128 + 15 -- SIGTERM +# +term_trap() { + dc_log 4 "Got SIGTERM, so shutting down." + run_parts "$DOCKER_EXIT_DIR" + sv_down + exit 143 +} + + +# +# Stage 0) Register signal handlers and redirect stderr +# + +exec 2>&1 +trap 'kill $!; term_trap' SIGTERM + +# +# Stage 1) run all entry scripts in $DOCKER_ENTRY_DIR +# + +run_parts "$DOCKER_ENTRY_DIR" + +# +# Stage 2) run provided arguments in the background +# Start services with: runsvdir -P ${SVDIR} +# + +"$@" & + +# +# Stage 3) wait forever so we can catch the SIGTERM +# +while true; do + tail -f /dev/null & wait $! +done diff --git a/asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-service.sh b/asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-service.sh new file mode 100755 index 0000000..79cef08 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/docker/bin/docker-service.sh @@ -0,0 +1,120 @@ +#!/bin/sh +# +# docker-service.sh +# +. docker-common.sh + +# use /etc/service if $SVDIR not already defined +SVDIR=${SVDIR-/etc/service} +DOCKER_SVLOG_DIR=${DOCKER_SVLOG_DIR-/var/log/sv} +DOCKER_RUN_DIR=${DOCKER_RUN_DIR-/var/run} + +# +# Define helpers +# +usage() { + cat <<-!cat + NAME + docker-service.sh + + SYNOPSIS + docker-service.sh [-d] [-f] [-h] [-l] [-n name] [-s file] [-q] command [args] + + OPTIONS + -d default down + -f remove lingering pid file at start up + -h print this text and exit + -l activate logging (svlogd) + -n name use this name instead of command + -s file source file + -q send stdout and stderr to /dev/null + + EXAMPLES + docker-service.sh "kopano-dagent -l" "-d kopano-grapi serve" + "-q -s /etc/apache2/envvars apache2 -DFOREGROUND -DNO_DETACH -k start" + + !cat +} + +base_name() { local base=${1##*/}; echo ${base%%.*} ;} + +pid_name() { + local dir_name=${1%%-*} + local pid_name=${1##*-} + echo "${DOCKER_RUN_DIR}/${dir_name}/${pid_name}.pid" +} + +add_opt() { + if [ -z "$options" ]; then + options=$1 + else + options="$options,$1" + fi +} + +# +# Define main function +# + +init_service() { + local redirstd= + local clearpid= + local sourcefile= + local sv_name cmd runsv_dir svlog_dir sv_log sv_down sv_force options + dc_log 7 "Called with args $@" + OPTIND=1 + while getopts ":dfhln:s:q" opts; do + case "${opts}" in + d) sv_down="down"; add_opt "down";; + f) sv_force="force"; add_opt "force";; + h) usage; exit;; + l) sv_log="log"; add_opt "log";; + n) sv_name="${OPTARG}"; add_opt "name";; + s) sourcefile=". ${OPTARG}"; add_opt "source";; + q) redirstd="exec >/dev/null"; add_opt "quiet";; + esac + done + shift $((OPTIND -1)) + cmd=$(which "$1") + sv_name=${sv_name-$(base_name $1)} + runsv_dir=$SVDIR/$sv_name + svlog_dir=$DOCKER_SVLOG_DIR/$sv_name + if [ -n "$sv_force" ]; then + forcepid="$(echo rm -f $(pid_name $sv_name)*)" + fi + shift + if [ ! -z "$cmd" ]; then + dc_log 5 "Setting up ($sv_name) options ($options) args ($@)" + mkdir -p $runsv_dir + cat <<-!cat > $runsv_dir/run + #!/bin/sh -e + exec 2>&1 + $forcepid + $redirstd + $sourcefile + exec $cmd $@ + !cat + chmod +x $runsv_dir/run + if [ -n "$sv_down" ]; then + touch $runsv_dir/down + fi + if [ -n "$sv_log" ]; then + mkdir -p $runsv_dir/log $svlog_dir + cat <<-!cat > $runsv_dir/log/run + #!/bin/sh + exec svlogd -tt $svlog_dir + !cat + chmod +x $runsv_dir/log/run + fi + else + dc_log 4 "Cannot find command." + fi + } + +# +# run +# + +for cmd in "$@" ; do + init_service $cmd +done diff --git a/asterisk/docker-asterisk-0.9.9/src/docker/entry.d/20-docker-print-versions b/asterisk/docker-asterisk-0.9.9/src/docker/entry.d/20-docker-print-versions new file mode 100755 index 0000000..eed13af --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/docker/entry.d/20-docker-print-versions @@ -0,0 +1,5 @@ +#!/bin/sh +# +# 20-docker-print-versions +# +dc_pkg_versions asterisk diff --git a/asterisk/docker-asterisk-0.9.9/src/docker/entry.d/50-docker-update-loglevel b/asterisk/docker-asterisk-0.9.9/src/docker/entry.d/50-docker-update-loglevel new file mode 100755 index 0000000..602f2e2 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/docker/entry.d/50-docker-update-loglevel @@ -0,0 +1,7 @@ +#!/bin/sh +# +# 50-docker-update-loglevel +# +# If SYSLOG_LEVEL is not empty update syslog level +# +dc_update_loglevel diff --git a/asterisk/docker-asterisk-0.9.9/src/notused/bin/astqueue.sh b/asterisk/docker-asterisk-0.9.9/src/notused/bin/astqueue.sh new file mode 100755 index 0000000..31658c8 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/notused/bin/astqueue.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# Used for testing +# + +source=${1-+15017122661} +destexten=${2-+15558675310} +message="${3-Local time is $(date)}" + +astspooldir=/var/spool/asterisk/outgoing +message_context=dp_entry_text_in +exten_context=dp_entry_answer + +maxretry=100 +retryint=30 +d_unique=$(date +%s) +d_friendly=$(date +%T_%D) +myrandom=$[ ( $RANDOM % 1000 ) + 1 ] + +filename="$destexten-$d_unique.$myrandom.call" + +cat <<-!cat > $astspooldir/$filename + Channel: Local/${destexten}@${exten_context} + CallerID: $source + Maxretries: $maxretry + RetryTime: $retryint + Context: $message_context + Extension: $destexten + Priority: 1 + Setvar: MESSAGE(body)=$message + Setvar: MESSAGE(to)=$destexten + Setvar: MESSAGE(from)=$source +!cat diff --git a/asterisk/docker-asterisk-0.9.9/src/notused/bin/relpath b/asterisk/docker-asterisk-0.9.9/src/notused/bin/relpath new file mode 100755 index 0000000..884458b --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/notused/bin/relpath @@ -0,0 +1,21 @@ +#!/bin/sh + +relpath() { + there="$1" + here="$(dirname $2)" + root="" + if [ ! -z $(echo "$there" | grep "^$here") ]; then + root="./" + else while [ -z $(echo "$there" | grep "^$here") ]; do + here=${here%/*} + root=${root}../ + done + fi + echo $root$(echo "$there" | sed "s|^$here/||g") +} + +# +# run +# + +relpath "$@" diff --git a/asterisk/docker-asterisk-0.9.9/src/notused/bin/voipbl.sh b/asterisk/docker-asterisk-0.9.9/src/notused/bin/voipbl.sh new file mode 100755 index 0000000..38de899 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/notused/bin/voipbl.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# +# This script creates an acl-blacklist.conf + +DOCKER_VOIPBL_FILE=${DOCKER_VOIPBL_FILE-/srv/var/spool/asterisk/acl/acl-blacklist.conf} + +wget -qO - http://www.voipbl.org/update/ | +sed 's/^/deny=/' > $DOCKER_VOIPBL_FILE diff --git a/asterisk/docker-asterisk-0.9.9/src/notused/entry.d/20-cronjob-voipbl b/asterisk/docker-asterisk-0.9.9/src/notused/entry.d/20-cronjob-voipbl new file mode 100644 index 0000000..e4eb7aa --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/notused/entry.d/20-cronjob-voipbl @@ -0,0 +1,46 @@ +#!/bin/sh +# +# 20-cronjob-voipbl +# +# DO NOT USE: blacklist is too long and asterisk chokes +# +# If DOCKER_ACL_CONF contains #include $DOCKER_VOIPBL_CONF create a +# VOIPBL cronjob +# Need to run this before 50_seed-asterisk-conf +# +DOCKER_VOIPBL_URL=${DOCKER_VOIPBL_URL-http://www.voipbl.org/update/} +DOCKER_VOIPBL_CONF=${DOCKER_VOIPBL_CONF-/var/spool/asterisk/acl/acl-blacklist.conf} +DOCKER_VOIPBL_CRON=${DOCKER_VOIPBL_CRON-/etc/periodic/daily/voipbl} +DOCKER_ACL_CONF=${DOCKER_ACL_CONF-$DOCKER_CONF_DIR/acl.conf} + + +# +# If there is no DOCKER_ACL_CONF file create it +# +if [ ! -f "$DOCKER_ACL_CONF" ]; then + cat <<-!cat > $DOCKER_ACL_CONF + [acl_blacklist] + #include $DOCKER_VOIPBL_CONF + !cat +fi + +# +# If DOCKER_ACL_CONF contains #include $DOCKER_VOIPBL_CONF then +# create the DOCKER_VOIPBL_CRON cronjob which downloads the voip black list +# into DOCKER_VOIPBL_FILE +# If DOCKER_VOIPBL_FILE does not exist run cronjob now +# +if grep -q "#include $DOCKER_VOIPBL_CONF" $DOCKER_ACL_CONF; then + mkdir -p $(dirname $DOCKER_VOIPBL_CONF) + cat <<-!cat > $DOCKER_VOIPBL_CRON + #!/bin/sh + wget -qO - $DOCKER_VOIPBL_URL | + sed 's/^[0-9]/deny = &/' > $DOCKER_VOIPBL_CONF + !cat + chmod a+x $DOCKER_VOIPBL_CRON + if [ ! -f "$DOCKER_VOIPBL_CONF" ]; then + $DOCKER_VOIPBL_CRON + fi +fi + + diff --git a/asterisk/docker-asterisk-0.9.9/src/notused/php/amiupdateconfig.class.inc b/asterisk/docker-asterisk-0.9.9/src/notused/php/amiupdateconfig.class.inc new file mode 100644 index 0000000..dec134b --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/notused/php/amiupdateconfig.class.inc @@ -0,0 +1,70 @@ +amiUpdate('Append',['Value-000000' => $ip]); +* $ami->amiUpdate('Delete',['Match-000000' => $ip]); +* $ami->amiUpdate('Delete'); + +*/ +require_once 'ami-class.php'; + +class AmiUpdateConfig extends \PHPAMI\Ami { + const DEFAULT_CONF_FILE = '/etc/asterisk/autoban.conf'; + const DEFAULT_CONF_VALS = [ + 'Action' => 'UpdateConfig', + 'ActionID' => 0, + 'SrcFilename' => 'pjsip.conf', + 'DstFilename' => 'pjsip.conf', + 'Reload' => 'res_pjsip', + 'PreserveEffectiveContext' => false, + 'Action-000000' => 'Append', + 'Cat-000000' => 'autoban', + 'Var-000000' => 'deny', + 'Value-000000' => null, + 'Match-000000' => null, + 'Line-000000' => null + ]; + public function __construct($config = null, array $optconfig = []) { + parent::__construct($config,$optconfig); + if (is_string($config) !== true) { + $config = self::DEFAULT_CONF_FILE; + } + $this->config['amiaction'] = self::DEFAULT_CONF_VALS; + if (file_exists($config) === true) { + $config_ini = parse_ini_file($config,true); + $this->config['amiaction'] = array_merge($this->config['amiaction'],$config_ini['amiaction']); + } + } + public function amiUpdate($action,$args = []) { + $parameters = array_merge($this->config['amiaction'], + [ 'Action-000000' => $action ], $args); + $res = $this->sendRequest('UpdateConfig',$parameters); + if ($res['Response'] !== 'Success') { + $this->log("$action failed.",self::LOG_ERROR); + var_dump($parameters); + var_dump($res); + return false; + } + $this->log("$action Success",self::LOG_WARN); + return true; + } + public function amiGetIp($parameters) { + if (is_array($parameters) && array_key_exists('RemoteAddress',$parameters)) { + $address = explode('/',$parameters['RemoteAddress']); + $ip = $address[2]; + return $ip; + } else { + return false; + } + } + public function amiGetValue($parameters,$key) { + if (is_array($parameters) && array_key_exists($key,$parameters)) { + return $parameters[$key]; + } else { + return false; + } + } +} +?> diff --git a/asterisk/docker-asterisk-0.9.9/src/privatedial/README.md b/asterisk/docker-asterisk-0.9.9/src/privatedial/README.md new file mode 120000 index 0000000..c0a00cb --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/privatedial/README.md @@ -0,0 +1 @@ +doc/privatedial.md \ No newline at end of file diff --git a/asterisk/docker-asterisk-0.9.9/src/privatedial/bin/minivm-send b/asterisk/docker-asterisk-0.9.9/src/privatedial/bin/minivm-send new file mode 100755 index 0000000..e8658c9 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/privatedial/bin/minivm-send @@ -0,0 +1,69 @@ +#!/bin/bash +# /usr/local/bin/minivm-send +# +#set -x +# +script_name=$(basename $0) +help() { +cat<<-!cat + DESCRIPTION + This script simplifies smtps connections for sendmail + USAGE + $script_name -H [OPTIONS] < message + OPTIONS + -e Also send log messages to stdout + -f For use in MAIL FROM + -H Mail host/ip and port + -h Print this text + -P Choose from: smtp, smtps, tls, starttls + -p Mail host authentication clear text password + -u Mail host authentication username +!cat +} + +# +# Arguments +# +sendmail_args=("-t") +logger_args=("-t" "$script_name[$$]") +while getopts ef:H:hP:p:u: option; do + case "${option}" in + e) logger_args+=("-s") ;; + f) sendmail_args+=("-f" "${OPTARG}") ;; + H) sendmail_host="${OPTARG}" ;; + h) help; exit 0 ;; + P) sendmail_proto="${OPTARG}" ;; + p) sendmail_args+=("-ap${OPTARG}") ;; + u) sendmail_args+=("-au${OPTARG}") ;; + esac +done + +# +# Protocol +# +case "$sendmail_proto" in +starttls) + sendmail_args+=("-H" "openssl s_client -quiet -tls1 -starttls smtp -connect $sendmail_host") ;; +smtps|tls) + sendmail_args+=("-H" "openssl s_client -quiet -tls1 -connect $sendmail_host") ;; +smtp|*) + sendmail_args+=("-S" "$sendmail_host") ;; +esac + +# +# Send email +# Asterisk pass the message via stdin to this script and +# that stream is inherited here +# +sendmail "${sendmail_args[@]}" &>/dev/null +sendmail_extival=$? + +# +# Log sendmail status and exit +# +if [ $sendmail_extival -eq 0 ]; then + logger "${logger_args[@]}" -p mail.info "INFO: Successfully sent mail ($sendmail_host)" +else + logger "${logger_args[@]}" -p mail.err "ERROR: Unable to send mail ($sendmail_host)" +fi +exit $sendmail_extival diff --git a/asterisk/docker-asterisk-0.9.9/src/privatedial/config/extensions.conf b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/extensions.conf new file mode 100644 index 0000000..b267b24 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/extensions.conf @@ -0,0 +1,351 @@ +;-------------------------------- PrivateDial ---------------------------------- +; Filename: extensions.conf +; This file is an Asterisk configuration file, part of the PrivateDial suite +; It is loaded by the pbx_config.so module. +; + +;-------------------------------- general -------------------------------------- +; This category loads include files. +; +[general] +#tryinclude extensions_local.conf + +;-------------------------------- globals -------------------------------------- +; Global options are defined in include files. +; +[globals](+) +;-------------------------------- sms +; Full path to SMS app +APP_SMS = /usr/share/php7/websms.php + +;-------------------------------- entry contexts ------------------------------- +; Calls enter the dialplan in one of these entries +; Local additions to these entries are defined in include files. +; +[dp_entry_call_inout](+) +include => dp_lookup +include => dp_ivr_recgreet +include => dp_call_inout + +[dp_entry_call_in](+) +include => dp_lookup +include => dp_call_in + +[dp_entry_text_inout](+) +include => dp_lookup +include => dp_text_inout + +[dp_entry_text_in](+) +include => dp_lookup +include => dp_text_in + +[dp_entry_answer](+) +include => dp_lookup +include => dp_answer + + +;-------------------------------- action contexts ------------------------------ + +;-------------------------------- dp_lookup +; hints are placed here see hint_exten in pjsip_wizard.conf +; +; Rewrite E.123 +; More than 6 characters and first is 0; assume national number so add + and country code +; More than 6 characters and first is 1-9, assume international number so add + +; +[dp_lookup] +exten => _0ZXXXXXX.,1,Goto(${CONTEXT},+${GLOBAL(CONTRY_CODE)}${EXTEN:1},1) +exten => _ZXXXXXX.,1,Goto(${CONTEXT},+${EXTEN},1) + +[dp_call_inout] +exten => _[+0-9].,1,NoOp() + same => n,Gosub(sub_dial_term,s,1(${HINT})) + same => n,Gosub(sub_voicemail,s,1(${HINT})) + same => n,Gosub(sub_dial_trunk,${EXTEN},1(${HINT})) + same => n,Hangup() + +[dp_call_in] +exten => _[+0-9].,1,NoOp() + same => n,Gosub(sub_dial_term,s,1(${HINT})) + same => n,Gosub(sub_voicemail,s,1(${HINT})) + same => n,Hangup() + +[dp_text_inout] +exten => _[+0-9].,1,NoOp() + same => n,Gosub(sub_rewrite_from,s,1) + same => n,Gosub(sub_text_term,s,1(${HINT})) + same => n,Gosub(sub_text_trunk,${EXTEN},1(${HINT})) + same => n,Hangup() + +[dp_text_in] +exten => _[+0-9].,1,NoOp() + same => n,Gosub(sub_decode_body,s,1) + same => n,Gosub(sub_text_term,s,1(${HINT})) + same => n,Hangup() + +[dp_answer] +;DEVICE_STATE = UNKNOWN | NOT_INUSE | INUSE | BUSY | INVALID | UNAVAILABLE | RINGING | RINGINUSE | ONHOLD +exten => _[+0-9].,1,Goto(dev-${DEVICE_STATE(${HINT})}) + same => n(dev-NOT_INUSE),NoOp() + same => n(dev-INUSE),NoOp() + same => n(dev-RINGING),NoOp() + same => n(dev-RINGINUSE),NoOp() + same => n(dev-ONHOLD),NoOp() + same => n(dev-UNAVAILABLE),NoOp() + same => n,Answer() + same => n(dev-UNKNOWN),NoOp() + same => n(dev-INVALID),NoOp() + same => n,Hangup() + +[dp_hangup] +exten => _[+0-9].,1,Hangup() + +;-------------------------------- dp_ivr_recgreet +; Record personal voicemail greeting messages interactive voice response +; +[dp_ivr_recgreet] +exten => _X,1,Verbose(3, "New caller, ${CALLERID(num)} dialed into the IVR.") + same => n,Set(endpoint=${CHANNEL(endpoint)}) + same => n,Set(mailboxes=${PJSIP_ENDPOINT(${endpoint},mailboxes)}) + same => n,Gotoif(${ISNULL(${endpoint})}?hangup:) + same => n,Answer() + same => n,Set(mailpath=${MINIVMACCOUNT(${mailboxes}:path)}) + same => n,Verbose(3, "Mailbox: ${mailboxes}, Creating new path: ${mailpath}") + same => n,System(mkdir -p ${mailpath}) + same => n,Goto(exten-${EXTEN}) + + same => n(exten-1),Verbose(3, "Caller ${endpoint} Record the temporary greeting.") + same => n,MinivmAccMess(${mailboxes},t) + same => n,Goto(exten-9) + + same => n(exten-2),Verbose(3, "Caller ${endpoint} Record the unavailable greeting.") + same => n,MinivmAccMess(${mailboxes},u) + same => n,Goto(exten-9) + + same => n(exten-3),Verbose(3, "Caller ${endpoint} Record the busy greeting.") + same => n,MinivmAccMess(${mailboxes},b) + same => n,Goto(exten-9) + + same => n(exten-4),Verbose(3, "Caller ${endpoint)} Record the account name.") + same => n,MinivmAccMess(${mailboxes},n) + same => n,Goto(exten-9) + + same => n(exten-5),Verbose(3, "MusicOnHold") + same => n,MusicOnHold() + same => n,Goto(exten-9) + + same => n(exten-6),Verbose(3, "Echo") + same => n,Playback(demo-echotest) + same => n,Echo() + same => n,Playback(demo-echodone) + same => n,Playback(vm-goodbye) + same => n,Goto(exten-9) + + same => n(exten-9),Background(basic-pbx-ivr-main) + same => n,WaitExten(10) + same => n,Background(basic-pbx-ivr-main) + same => n(hangup),Hangup() + +exten => i,1,Playback(option-is-invalid) + same => n,Goto(9,exten-9) + +exten => t,1,Playback(are-you-still-there) + same => n,Goto(9,exten-9) + +;-------------------------------- subroutines ---------------------------------- +; Syntax: Gosub(context,extension,priority(${ARG1},${ARG3},${ARG4})) +; + +;-------------------------------- sub_dial_term +; Dial user subroutine for PJSIP +; Dial all pjsip contacts of an endpoint +; Usage: Gosub(sub_dial_term,s,1(${HINT})) +; ${ARG1} - pjsip tech/endpoint: ${HINT}, eg PJSIP/myuser +; +; Implementation details +; Dial all registered contacts of the endpoint. Return if there are none. +; Do not hangup, so that we can pass the call to sub_voicemail +; +[sub_dial_term] +exten => s,1,Set(LOCAL(endpoint)=${ARG1:6}) ; strip PJSIP/ from endpoint name + same => n,Gotoif(${ISNULL(${endpoint})}?return:) + same => n,Set(LOCAL(contacts)=${PJSIP_DIAL_CONTACTS(${endpoint})}) + same => n,Gotoif(${ISNULL(${contacts})}?return:) + same => n,Verbose(2, "Call from CID: ${CALLERID(all)}, dialing all contacts of endpoint: ${endpoint}.") + same => n,Dial(${contacts}${GLOBAL(DIAL_TIMEOUT)}) + same => n(return),Return() + +;-------------------------------- sub_dial_trunk +; Dial trunk subroutine for PJSIP +; Usage: Gosub(sub_dial_trunk,${EXTEN},1(${HINT})) +; ${EXTEN} - Extension, eg 0046735698294 +; ${ARG1} - pjsip tech/endpoint: ${HINT}, eg PJSIP/myuser +; +; Implementation details +; Dial EXTEN using ${TRUNK_ENDPOINT} which is defined in endpoint using set_var. +; In keeping with coding style, do not hangup. +; The channel variable ${TRUNK_ENDPOINT} holds the SIP trunk endpoint and +; needs be set on endpoints. This allows mutiple SIP trunk endpoints to be used. +; +[sub_dial_trunk] +exten => _[+0-9].,1,NoOP(Dialing out originating CID ${CALLERID(all)}) + same => n,Dial(PJSIP/${EXTEN}@${TRUNK_ENDPOINT}) + same => n(return),Return() + +;-------------------------------- sub_voicemail +; Voicemail subroutine: +; Usage: Gosub(sub_voicemail,s,1(${HINT})) +; ${ARG1} - pjsip tech/endpoint: ${HINT}, eg PJSIP/myuser +; ${ARG2} - Status of the call: ${DIALSTATUS}, one of: +; CHANUNAVAIL, CONGESTION, BUSY, NOANSWER, ANSWER, CANCEL, DONTCALL, TORTURE +; +; Implementation details +; Depending on DIALSTATUS direct caller to voice mail and then hangup. +; Only return from here if callee has no endpoint, in which case we assume +; callee is external. +; MiniVM does not work unless there is a mailbox directory, so always create it. +; +[sub_voicemail] +exten => s,1,Set(LOCAL(endpoint)=${ARG1:6}) ; strip PJSIP/ from endpoint name + same => n,Gotoif(${ISNULL(${endpoint})}?return:) + same => n,Set(LOCAL(mailboxes)=${PJSIP_ENDPOINT(${endpoint},mailboxes)}) + same => n,Gotoif(${ISNULL(${mailboxes})}?mailbox-NULL:) + same => n,Set(mailpath=${MINIVMACCOUNT(${mailboxes}:path)}) + same => n,System(mkdir -p ${mailpath}) + same => n,Goto(dial-${DIALSTATUS}) + same => n(return),Return() + + same => n(mailbox-NULL),NoOp() + same => n,Playback(please-try-call-later) + same => n,Hangup() + + same => n(dial-CHANUNAVAIL),NoOp() + same => n(dial-CONGESTION),NoOp() + same => n(dial-NOANSWER),NoOp() + same => n(dial-),NoOp() +; same => n,MinivmGreet(${mailboxes},u) + same => n,Goto(mail-RECORD) + + same => n(dial-BUSY),NoOp() +; same => n,MinivmGreet(${mailboxes},b) + + same => n(mail-RECORD),NoOp() + same => n,MinivmGreet(${mailboxes},s) + same => n,MinivmRecord(${mailboxes}${GLOBAL(VOICEMAIL_RECGAINDB)}) + ; If the caller hangs up after the recording, + ; the only way to send the email and clean up is to execute in the "h" + same => n,Hangup() + + same => n(dial-CANCEL),NoOp() + same => n(dial-DONTCALL),NoOp() + same => n(dial-TORTURE),NoOp() + same => n(dial-ANSWER),NoOp() + same => n,Hangup() + +; send email and clean up +exten => h,1,Goto(recd-${MVM_RECORD_STATUS}) + + same => n(recd-SUCCESS),NoOp() + same => n(recd-USEREXIT),NoOp() + same => n,MinivmNotify(${mailboxes}${GLOBAL(VOICEMAIL_TEMPLATE)}) + same => n,Goto(mail-${MVM_NOTIFY_STATUS}) + + same => n(mail-SUCCESS),NoOp() + same => n,MinivmDelete() + same => n,Goto(recd-) + + same => n(mail-FAILED),NoOp() + same => n(recd-FAILED),NoOp() + same => n,Playback(vm-incorrect-mailbox) + + same => n(recd-),NoOp() + same => n,Hangup() + +;-------------------------------- sub_rewrite_from +; Rewrite the MESSAGE(from) subroutine for PJSIP +; Usage: Gosub(sub_rewrite_from,s,1) +; +; Implementation details +; Some clients sets the MESSAGE(from) to endpoint@domain +; But we want the MESSAGE(from) to be set to the endpoint extension, ie, its hint +; so assume the MESSAGE(from) is of the form endpoint@domain and +; try to look up the endpoint's hint. +; if successful rewrite the MESSAGE(from) +; +[sub_rewrite_from] +exten => s,1,Verbose(3,"Original message from ${MESSAGE(from)}") + same => n,Set(LOCAL(endpoint)=${CUT(MESSAGE(from),@,1)}) + same => n,Set(LOCAL(endpoint)=${CUT(endpoint,:,2)}) + same => n,Gotoif(${ISNULL(${endpoint})}?return:) + same => n,Set(LOCAL(from)=${PJSIP_ENDPOINT(${endpoint},@hint_exten)}) + same => n,Gotoif(${ISNULL(${from})}?return:) + same => n,Set(MESSAGE(from)=${from}) + same => n,Set(WEBSMS_INDEX=${PJSIP_ENDPOINT(${endpoint},WEBSMS_INDEX)}) + same => n,Verbose(3,"Updated message from ${MESSAGE(from)}, WEBSMS_INDEX: ${WEBSMS_INDEX}") + same => n(return),Return() + +;-------------------------------- sub_decode_body +; URL decode the MESSAGE(body) subroutine +; Usage: Gosub(sub_decode_body,s,1) +; +; Implementation details +; If MESSAGE_ENCODE = rfc3986 then the MESSAGE(body) is URL encoded +; (using RFC3986 which supersedes RFC2396) in the callfile, so decode it here. +; +[sub_decode_body] +exten => s,1,Gotoif(${ISNULL(${MESSAGE_ENCODE})}?return:) + same => n,GotoIf($[ ${MESSAGE_ENCODE} != rfc3986 ]?return:) + same => n,Verbose(3,"Original message body ${MESSAGE(body)}") + same => n,Set(MESSAGE(body)=${URIDECODE(${MESSAGE(body)})}) + same => n,Verbose(3,"Updated message body ${MESSAGE(body)}") + same => n(return),Return() + +;-------------------------------- sub_text_term +; Instant messaging subroutine for PJSIP +; Send message to all pjsip contacts of an endpoint +; Usage: Gosub(sub_text_term,s,1(${HINT})) +; ${EXTEN} - Extension, eg 0735698294 +; ${ARG1} - pjsip tech/endpoint: ${HINT}, eg PJSIP/myuser +; +; Implementation details +; PJSIP_DIAL_CONTACTS() return all contact URLs separated by an "&", eg: +; PJSIP/myuser/sip:myuser@10.10.10.100:61863;option=value&PJSIP/myuser/sip:myuser@217.103.237.202:35678;option=value +; Within a While() loop, we cut this string at the "&" using ${SHIFT(contacts,&):6}. +; The ":6" strips off the initial "PJSIP/". +; MessageSend() needs the URL to be slightly reformatted, eg +; pjsip:myuser/sip:myuser@10.10.10.100:61863;option=value +; so we simply prepend with "pjsip:" +; MessageSend() accepts but ignores any provided options +; +[sub_text_term] +exten => s,1,Verbose(2, "Text User, To: ${MESSAGE(to)}, Hint: ${ARG1}, From: ${MESSAGE(from)}, CID: ${CALLERID(all)}, Body: ${MESSAGE(body)}") + same => n,Set(LOCAL(endpoint)=${CUT(ARG1,/,2)}) + same => n,Gotoif(${ISNULL(${endpoint})}?return:) + same => n,Set(LOCAL(contacts)=${PJSIP_DIAL_CONTACTS(${endpoint})}) + same => n,While($["${SET(contact=${SHIFT(contacts,&):6})}" != ""]) + same => n,MessageSend(pjsip:${contact},${MESSAGE(from)}) + same => n,Verbose(2, "Send status is ${MESSAGE_SEND_STATUS}") + same => n,EndWhile + same => n(return),Return() + +;-------------------------------- sub_text_trunk +; Instant messaging subroutine for PJSIP +; Send message to trunk via curl +; Usage: Gosub(sub_text_trunk,${EXTEN},1(${HINT})) +; ${EXTEN} - Extension, eg 0735698294 +; ${ARG1} - pjsip tech/endpoint: ${HINT}, eg PJSIP/myuser +; +; Implementation details +; To distinguish between local and external numbers we use the HINT +; If the HINT is null we assume that it is an external number +; AGISTATUS is one of SUCCESS, FAILURE, NOTFOUND, HANGUP +; The channel variable ${WEBSMS_INDEX} can be set on endpoints to select which +; configuration to use. +; +[sub_text_trunk] +exten => _[+0-9].,1,Verbose(2, "Text Out, To: ${MESSAGE(to)}, Hint: ${ARG1}, From: ${MESSAGE(from)}, CID: ${CALLERID(all)}, Body: ${MESSAGE(body)}, using Index: ${WEBSMS_INDEX}") + same => n,Set(LOCAL(endpoint)=${CUT(ARG1,/,2)}) + same => n,Gotoif(${ISNULL(${endpoint})}?:return) + same => n,AGI(${GLOBAL(APP_SMS)},${EXTEN},${MESSAGE(from)},${QUOTE(${MESSAGE(body)})},${WEBSMS_INDEX}) + same => n,Verbose(2, "AGI status is ${AGISTATUS}") + same => n(return),Return() diff --git a/asterisk/docker-asterisk-0.9.9/src/privatedial/config/extensions_local.conf b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/extensions_local.conf new file mode 100644 index 0000000..1815302 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/extensions_local.conf @@ -0,0 +1,34 @@ +;-------------------------------- PrivateDial ---------------------------------- +; Filename: extensions_local.conf +; This file is an Asterisk configuration file, part of the PrivateDial suite +; It is included by the extensions.conf file. +; + +;-------------------------------- globals -------------------------------------- +; include file providing dialing texting options used in context globals +; + +;-------------------------------- dialing + +[globals] +CONTRY_CODE = 46 +DIAL_TIMEOUT =,30 + +;-------------------------------- voice mail + +VOICEMAIL_TEMPLATE =,en_US_email +VOICEMAIL_RECGAINDB =,g(12) + +;-------------------------------- entries -------------------------------------- +; Calls enter the dialplan in one of these entries +; + +[dp_entry_call_inout] + +[dp_entry_call_in] + +[dp_entry_text_inout] + +[dp_entry_text_in] + +[dp_entry_answer] diff --git a/asterisk/docker-asterisk-0.9.9/src/privatedial/config/minivm.conf b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/minivm.conf new file mode 100644 index 0000000..ee00e61 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/minivm.conf @@ -0,0 +1,36 @@ +;-------------------------------- PrivateDial ---------------------------------- +; Filename: minivm.conf +; This file is an Asterisk configuration file, part of the PrivateDial suite. +; It is loaded by the app_minivm.so module. +; + +[general] +; DESCRIPTION +; This script simplifies smtps connections for sendmail +; USAGE +; minivm-send -H [OPTIONS] < message +; OPTIONS +; -e Also send log messages to stdout +; -f For use in MAIL FROM +; -H Mail host/ip and port +; -h Print this text +; -P Choose from: smtp, smtps, tls, starttls +; -p Mail host authentication clear text password +; -u Mail host authentication username +; +mailcmd = minivm-send -H mx.example.com:587 -P starttls -u username -p password -f voicemail-noreply@example.com + +format = wav49 + +;logfile = /var/log/asterisk/minivm.log +;minmessage = 3 ; asterisk crashes if this is set? :O + +[template-en_US_email] +fromemail = voicemail-noreply@example.com +fromaddress = voicemail +messagebody = ${MVM_CALLERID} left you a ${MVM_DUR} long message on ${MVM_DATE} UTC, see attachment. +subject = [voicemail] from ${MVM_CALLERID} +charset = iso-8859-1 +attachmedia = yes +dateformat = %A, %d %B %Y at %H:%M:%S +locale = sv_SE diff --git a/asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip.conf b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip.conf new file mode 100644 index 0000000..4f638e2 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip.conf @@ -0,0 +1,15 @@ +;-------------------------------- PrivateDial ---------------------------------- +; Filename: pjsip.conf +; This file is an Asterisk configuration file, part of the PrivateDial suite. +; It is loaded by the chan_pjsip.so module. +; + +;-------------------------------- global --------------------------------------- + +[global] +type = global +user_agent = Platform PBX + +;-------------------------------- includes ------------------------------------- + +#tryinclude pjsip_transport.conf diff --git a/asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip_endpoint.conf b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip_endpoint.conf new file mode 100644 index 0000000..ec48156 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip_endpoint.conf @@ -0,0 +1,36 @@ +;-------------------------------- PrivateDial ---------------------------------- +; Filename: pjsip_endpoint.conf +; This file is an Asterisk configuration file, part of the PrivateDial suite. +; It is included by the pjsip_wizard.conf file +; + +;-------------------------------- templates ------------------------------------ + +[w_term:mydoe](!,w_term_io) +endpoint/set_var = TRUNK_ENDPOINT=itsp:mydoe +endpoint/set_var = WEBSMS_INDEX= + +;-------------------------------- sip trunks ----------------------------------- + +[itsp:mydoe](w_trunk) +remote_hosts = sip.mydoe.com +sends_auth = yes +sends_registrations = yes +outbound_auth/username = username +outbound_auth/password = password + +;-------------------------------- sip terminals -------------------------------- + +[john.doe](w_term:mydoe) +hint_exten = +12025550160 +endpoint/callerid = John Doe <+12025550160> +endpoint/mailboxes = john.doe@example.com +inbound_auth/username = john.doe +inbound_auth/password = password + +[jane.doe](w_term:mydoe) +hint_exten = +12025550183 +endpoint/callerid = Jane Doe <+12025550183> +endpoint/mailboxes = jane.doe@example.com +inbound_auth/username = jane.doe +inbound_auth/password = password diff --git a/asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip_transport.conf b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip_transport.conf new file mode 100644 index 0000000..991d219 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip_transport.conf @@ -0,0 +1,29 @@ +;-------------------------------- PrivateDial ---------------------------------- +; Filename: pjsip_transport.conf +; This file is an Asterisk configuration file, part of the PrivateDial suite +; It is included by the pjsip.conf file. +; + +;-------------------------------- transports ----------------------------------- + +[t_wan](!) +type = transport +bind = 0.0.0.0:5060 +domain = example.com +external_signaling_address = sip.example.com +external_media_address = sip.example.com +tos = cs3 +cos = 3 + +[udp](t_wan) +protocol = udp + +[tcp](t_wan) +protocol = tcp + +[tls](t_wan) +bind = 0.0.0.0:5061 +cert_file = /etc/ssl/asterisk/cert.pem +priv_key_file = /etc/ssl/asterisk/priv_key.pem +protocol = tls +method=tlsv1_2 diff --git a/asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip_wizard.conf b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip_wizard.conf new file mode 100644 index 0000000..a05bc09 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/privatedial/config/pjsip_wizard.conf @@ -0,0 +1,67 @@ +;-------------------------------- PrivateDial ---------------------------------- +; Filename: pjsip_wizard.conf +; This file is an Asterisk configuration file, part of the PrivateDial suite. +; It is loaded by the res_pjsip_config_wizard.so module. +; + +;-------------------------------- templates ------------------------------------ + +[_qos](!) +endpoint/tos_audio = ef +endpoint/tos_video = af41 +endpoint/cos_audio = 5 +endpoint/cos_video = 4 + +[_nat](!) +endpoint/rewrite_contact = yes +endpoint/direct_media = no +endpoint/rtp_symmetric = yes + +[_sdes](!) +endpoint/media_encryption_optimistic = yes +endpoint/media_encryption = sdes + +[_dtls](!) +endpoint/media_encryption_optimistic = yes +endpoint/media_encryption = dtls +endpoint/dtls_auto_generate_cert = yes + +[_term](!) +accepts_auth = yes +accepts_registrations = yes +endpoint/allow = !all,ulaw,h263p,h263,h264 +endpoint/bind_rtp_to_media_address = yes +aor/max_contacts = 10 +aor/remove_existing = yes +aor/minimum_expiration = 120 +aor/qualify_frequency = 60 + +[_trunk](!) +endpoint/allow = !all,ulaw +endpoint/allow_subscribe = no +aor/qualify_frequency = 60 + +[_hint](!) +has_hint = yes +hint_context = dp_lookup + +[_in](!) +endpoint/context = dp_entry_call_in +endpoint/message_context = dp_entry_text_in + +[_inout](!) +endpoint/context = dp_entry_call_inout +endpoint/message_context = dp_entry_text_inout + +[w_term_io](!,_nat,_qos,_sdes,_hint,_term,_inout) +type = wizard + +[w_term_i](!,_nat,_qos,_sdes,_hint,_term,_in) +type = wizard + +[w_trunk](!,_nat,_qos,_trunk,_in) +type = wizard + +;-------------------------------- includes ------------------------------------- + +#tryinclude pjsip_endpoint.conf diff --git a/asterisk/docker-asterisk-0.9.9/src/privatedial/doc/privatedial.md b/asterisk/docker-asterisk-0.9.9/src/privatedial/doc/privatedial.md new file mode 100644 index 0000000..22e8fe6 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/privatedial/doc/privatedial.md @@ -0,0 +1,242 @@ +# PrivateDial + +PrivateDial is a suite of [Asterisk configuration files](https://wiki.asterisk.org/wiki/display/AST/Asterisk+Configuration+Files). This configuration is tailored to residential use cases, supporting the capabilities of mobile smart phones, that is, voice, video, instant messaging or SMS, and voice mail delivered by email. + +It uses the [PJSIP](https://www.pjsip.org/) [channel driver](https://wiki.asterisk.org/wiki/display/AST/Configuring+res_pjsip) and therefore natively support simultaneous connection of several soft-phones to each user account/endpoint. + +The underlying design idea is to separate the dial plan functionality from the user data. To achieve this all user specific data has been pushed out from the main `extensions.conf` file. + +## Features + +Feature list follows below + +- Calls and SMS between local endpoints. +- ITSP originating (incoming) SIP voice calls. +- ITSP termination (outgoing) SIP voice call. +- WebSMS; SMS to and from ITSP. +- [MiniVoiceMail](https://wiki.asterisk.org/wiki/display/AST/Asterisk+16+Application_MinivmRecord) + + +## Configuration files + +The suite of Asterisk configuration files making up PrivateDial is summarized below. + +### Configuration files overview + +The configuration files making up PrivateDial are tabulated below. + +| File name | Description | +| --------------------- | ------------------------------------------------------------ | +| extensions.conf | The dial plan, defining the data flow of calls and messages | +| extensions_local.conf | Use case specific global variables used in extensions.conf | +| minivm.conf | Define mail sever URL and authentication credentials which voice mail email notifications will be sent | +| pjsip.conf | Use case specific global variables used by the PJSIP driver | +| pjsip_transport.conf | Defines SIP transport, protocol, port, host URL | +| pjsip_wizard.conf | Defines templates for sip trunk and soft-phone endpoints | +| pjsip_endpoint.conf | Defines sip trunk and soft-phone endpoints | + +When configuring the asterisk sever the following files often needs to be updated: `pjsip_transport.conf` and `minivm.conf`. The remaining task is, once the severer has been configured, to add and maintain sip trunk and soft-phone endpoints, which is kept in `pjsip_endpoint.conf`. + +## Usage + +### SIP Trunk + +PJSIP endpoints are defined using the [PJSIP Wizard](https://wiki.asterisk.org/wiki/display/AST/PJSIP+Configuration+Wizard) in the configuration file `pjsip_endpoint.conf`. For convenience the template, `w_trunk` has been defined in `pjsip_wizard.conf`. + +Add an endpoint entry in `pjsip_endpoint.conf` based on the setup instructions provided by your trunk provider. This entry also hold your authentication credentials. + +`pjsip_endpoint.conf` + +```ini +[itsp:mydoe](w_trunk) +remote_hosts = sip.mydoe.com +sends_auth = yes +sends_registrations = yes +outbound_auth/username = username +outbound_auth/password = password +``` + +With some ITSP SIP servers you need to explicitly state which transport to use. In such case add the folowing to the section above; `transport = udp`, for UDP. + +### SIP Users + +PJSIP endpoints are defined using the [PJSIP Wizard](https://wiki.asterisk.org/wiki/display/AST/PJSIP+Configuration+Wizard) in the configuration file `pjsip_endpoint.conf`. For convenience the template, `w_term_io` and `w_term_i` has been defined in `pjsip_wizard.conf`. + +Add an endpoint entry in `pjsip_endpoint.conf` for each user. Each user can simultaneously connect with several soft-phones, using the same account. + +`pjsip_endpoint.conf` + +```ini +[w_term:mydoe](!,w_term_io) +endpoint/set_var = TRUNK_ENDPOINT=itsp:mydoe +endpoint/set_var = WEBSMS_INDEX= + +[john.doe](w_term:mydoe) +hint_exten = +12025550160 +endpoint/callerid = John Doe <+12025550160> +endpoint/mailboxes = john.doe@example.com +inbound_auth/username = john.doe +inbound_auth/password = password +``` + +You also need to configure WebSMS for SMS to work, see separate documentation. + +### Outgoing SMTP email server + +PrivateDial use [MiniVoiceMail](https://wiki.asterisk.org/wiki/display/AST/Asterisk+16+Application_MinivmRecord) to deliver voice mail messages via email with attached sound files. For this to work a separate SMTP email server need to have been set up. This can for example be achieved by using the image [mlan/postfix-amavis](https://hub.docker.com/repository/docker/mlan/postfix-amavis). With a functional email server, configure MiniVM to connect to it by providing its URL and authentication credentials in `minivm.conf` + +`minivm.conf` + +```ini +[general] +mailcmd = minivm-send -H mx.example.com:587 -P starttls -u username -p password -f voicemail-noreply@example.com +``` + +### SIP Networking + +Here we describe 3 aspects of SIP networking that often needs to be addressed. Communication with devices on local networks, Intrusion prevention using non-standard ports. Privacy using encryption. + +#### Network Address Translation (NAT) + +When communicating with devices on local networks a more elaborate mechanism using (NAT) needs to be configured allowing server and client locate each other. Assuming that the SIP server has the following external URL; `sip.example.com`, make sure to update `pjsip_transport.conf` so it includes the snippet below. + +`pjsip_transport.conf` + +```ini +[t_wan](!) +type = transport +bind = 0.0.0.0:5060 +domain = example.com +external_signaling_address = sip.example.com +external_media_address = sip.example.com +``` + +#### Custom SIP ports + +When using non-standard ports the amount of attacks drop significantly, so it might be considered whenever practical. When changing port numbers they need to be updated both for docker and asterisk. To exemplify, assume we want to use 5560 for UDP and TCP and 5561 for TLS, in which case we update the configuration in two places: + +- docker/docker-compose, eg, `docker run -p "5560-5561:5560-5561" -p"5560:5560/udp" ...` +- asterisk transport in `pjsip_transport.conf` + +`pjsip_transport.conf` + +```ini +[t_wan](!) +type = transport +bind = 0.0.0.0:5560 +... +[tls](t_wan) +bind = 0.0.0.0:5561 +... +``` + +#### TLS Certificate and key + +To enable encryption of both the session and data packages (TLS and SDES SRTP) a [TLS/SSL server certificate](https://en.wikipedia.org/wiki/Public_key_certificate) and key are needed. If the certificate and key do not exist when the container starts a [self-signed certificate](https://en.wikipedia.org/wiki/Self-signed_certificate) and private key are automatically generated. The default file names for these are defined below. Should the certificate and key be available be other means they can be copied to the container using this names. If other file names are referred also update their names in `pjsip_transport.conf`. + +`pjsip_transport.conf` + +```ini +[tls](t_wan) +cert_file = /etc/ssl/asterisk/cert.pem +priv_key_file = /etc/ssl/asterisk/priv_key.pem +``` + +There is also a mechanism to use ACME lets encrypt certificates, which also use these file names. + +## Implementation + +### Dialplan + +The PrivateDial has its dialplan contexts organized in 3 levels. The entry, action and subroutine contexts. A SIP event will trigger the execution of the PrivateDial dial plan staring on one of the entry contexts. The entry contexts include some of the action contexts, and the action contexts call the subroutines. + +#### Entry context + +The entry contexts are used to grant more access to users calling or texting as compared to external trunk calls or texts. All entry context start with including the `dp_lookup` context so that extension hints are always available. + +```ini +[dp_entry_call_inout](+) +include => dp_lookup +include => dp_ivr_recgreet +include => dp_call_inout + +[dp_entry_call_in](+) +include => dp_lookup +include => dp_call_in + +[dp_entry_text_inout](+) +include => dp_lookup +include => dp_text_inout + +[dp_entry_text_in](+) +include => dp_lookup +include => dp_text_in + +[dp_entry_answer](+) +include => dp_lookup +include => dp_answer +``` + +#### Action context + +The action contexts calls the subroutines. Most subroutines use the `${HINT}` channel variable to identify the endpoint so `${EXTEN}` is set to the special `s`. Each subroutine is called in its turn and the call is not hung up until all subroutine calls has been made. + +```ini +[dp_lookup] +; hints are placed here see hint_exten in pjsip_wizard.conf +exten => _0ZXXXXXX.,1,Goto(${CONTEXT},+${GLOBAL(CONTRY_CODE)}${EXTEN:1},1) +exten => _ZXXXXXX.,1,Goto(${CONTEXT},+${EXTEN},1) + +[dp_call_inout] +exten => _[+0-9].,1,NoOp() + same => n,Gosub(sub_dial_term,s,1(${HINT})) + same => n,Gosub(sub_voicemail,s,1(${HINT})) + same => n,Gosub(sub_dial_trunk,${EXTEN},1(${HINT})) + same => n,Hangup() + +[dp_call_in] +exten => _[+0-9].,1,NoOp() + same => n,Gosub(sub_dial_term,s,1(${HINT})) + same => n,Gosub(sub_voicemail,s,1(${HINT})) + same => n,Hangup() + +[dp_text_inout] +exten => _[+0-9].,1,NoOp() + same => n,Gosub(sub_rewrite_from,s,1) + same => n,Gosub(sub_text_term,s,1(${HINT})) + same => n,Gosub(sub_text_trunk,${EXTEN},1(${HINT})) + same => n,Hangup() + +[dp_text_in] +exten => _[+0-9].,1,NoOp() + same => n,Gosub(sub_decode_body,s,1) + same => n,Gosub(sub_text_term,s,1(${HINT})) + same => n,Hangup() + +[dp_answer] +exten => _[+0-9].,1,Goto(dev-${DEVICE_STATE(${HINT})}) + same => n(dev-NOT_INUSE),NoOp() + same => n(dev-INUSE),NoOp() + same => n(dev-RINGING),NoOp() + same => n(dev-RINGINUSE),NoOp() + same => n(dev-ONHOLD),NoOp() + same => n(dev-UNAVAILABLE),NoOp() + same => n,Answer() + same => n(dev-UNKNOWN),NoOp() + same => n(dev-INVALID),NoOp() + same => n,Hangup() +``` + +#### Subroutine context + +The file `extension.conf` include some in line documentation of the subroutines. + +Subroutines does not hang up but instead returns the data flow to the calling context. (CHECK with sub_voicemail). + +Most subroutines use the `${HINT}` channel variable to identify the endpoint so `${EXTEN}` is set to the special `s`. + +When calling and texting endpoints an attempts are made to contact all contacts of the endpoints, such that for inbound calls all registered contacts (smart-pones) will ring and also receive inbound SMS. + +### Presence + +Asterisk support [presence state](https://wiki.asterisk.org/wiki/display/AST/Presence+State) an indicator that conveys the state of an endpoint to other endpoints. But, unfortunately, presence is only supported for Sangama/Digium phones, not for softphones. Consequentely, no attmpt has been made to support presence state in PrivateDial. diff --git a/asterisk/docker-asterisk-0.9.9/src/websms/README.md b/asterisk/docker-asterisk-0.9.9/src/websms/README.md new file mode 120000 index 0000000..6d1fb45 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/websms/README.md @@ -0,0 +1 @@ +doc/websms.md \ No newline at end of file diff --git a/asterisk/docker-asterisk-0.9.9/src/websms/config/websms.conf b/asterisk/docker-asterisk-0.9.9/src/websms/config/websms.conf new file mode 100644 index 0000000..5a69042 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/websms/config/websms.conf @@ -0,0 +1,22 @@ +; +; websms.conf +; +; This file hold user customization of http sms +; originating and termination service. +; + +[websms] +url_host = https://api.example.com +url_path = /sms/send/ +auth_user = user +auth_secret = secret + +[websmsd] +url_path [1] = /hook/1 +resp_ack [1] = "SMS received on /hook/1" +url_path [2] = /hook/2 +resp_ack [2] = "SMS received on /hook/2" + +[astqueue] +channel_context = dp_entry_answer +context = dp_entry_text_in diff --git a/asterisk/docker-asterisk-0.9.9/src/websms/doc/websms.conf.sample b/asterisk/docker-asterisk-0.9.9/src/websms/doc/websms.conf.sample new file mode 100644 index 0000000..04c4023 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/websms/doc/websms.conf.sample @@ -0,0 +1,47 @@ +; +; websms.conf.sample +; +; This file hold user customization of the websms originate and termination. +; This is a php ini file. Luckily its syntax is similar to other asterisk conf files. +; "yes" and "no" have to be within quotation marks otherwise they will be +; interpreted as Boolean. +; + +;[websms] +;auth_method = basic ;eg "plain", "zadarma" method to authenticate sms request +;auth_secret = "" ;authentication password/secret +;auth_user = "" ;authentication username/key +;key_body = Body ;http POST key name holding the sms message +;key_from = From ;http POST key name holding sms originating phone number +;key_secret = "" ;http POST key name holding the password/secret when using auth_method=plain +;key_to = To ;http POST key name holding sms destination phone number +;key_user = "" ;http POST key name holding the username/key when using auth_method=plain +;resp_check = "" ;http POST key=value to check, eg "status=success" +;url_host = http://localhost ;scheme and host, eg https://api.expmple.com +;url_path = / ;complete url will be +;val_numform = "" ;eg E164; omit leading + and 0 in phone numbers, or E123 +;val_static = "" ;comma separated key=value pairs to add +;val_unicode = "" ;set to "UCS-2" to limit Unicode characters to U+FFFF + +;[websmsd] +;key_body = Body ;http POST key name holding the sms message +;key_echo = "" ;some ITSP test that the client respond by echoing it value, eg "zd_echo" +;key_from = From ;http POST key name holding sms origination phone number +;key_to = To ;http POST key name holding sms destination phone number +;prox_addr = 172.16.0.0/12,192.168.0.0/16 ;Trust "prox_header" from these IPs, eg 10.0.0.0/8 +;prox_header = HTTP_X_FORWARDED_FOR ;Behind a proxy this header hold the real client IP +;remt_addr = "" ;if defined, only listed addrs are accepted, eg 185.45.152.42,3.104.90.0/24,3.1.77.0/24 +;resp_ack = "" ;report success, eg, "" +;url_path = "" ;if defined, only listed URIs are accepted, eg /,/trunk1. URIs must start with "/". + +;[astqueue] +;outgoingdir = /var/spool/asterisk/outgoing ;directory where asterisk picks up call files +;stagingdir = /var/spool/asterisk/staging ;create call file here and then move to outgoing +;waittime = 45 ;how many seconds to wait for an answer before the call fails +;maxretries = 0 ;number of retries before failing. 0 = don't retry if fails +;retrytime = 300 ;how many seconds to wait before retry +;archive = "no" ;"yes" = save call file to /var/spool/asterisk/outgoing_done +;channel_context = default ;dialplan context to answer the call, ie set up the channel +;context = default ;dialplan context to handle the sms +;priority = 1 ;dialplan priority to handle the sms +;message_encode = rfc3986 ;only single line allowed in call file so url-encoding message diff --git a/asterisk/docker-asterisk-0.9.9/src/websms/doc/websms.md b/asterisk/docker-asterisk-0.9.9/src/websms/doc/websms.md new file mode 100644 index 0000000..3c9e0f4 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/websms/doc/websms.md @@ -0,0 +1,342 @@ +# WebSMS + +The [Short Message Service (SMS)](https://en.wikipedia.org/wiki/SMS) [text messaging](https://en.wikipedia.org/wiki/Text_messaging) service, introduced in 1993, enabled mobile devices to exchange short text messages, using the [Short Message Peer-to-Peer (SMPP)](https://en.wikipedia.org/wiki/Short_Message_Peer-to-Peer) protocol. The [Session Initiation Protocol (SIP)](https://en.wikipedia.org/wiki/Session_Initiation_Protocol) include provision for [Instant Messaging (IM)](https://en.wikipedia.org/wiki/Instant_messaging) using the [SIMPLE](https://en.wikipedia.org/wiki/SIMPLE_(instant_messaging_protocol)) protocol extension, serving a similar purpose. + +Asterisk supports [SIMPLE](https://en.wikipedia.org/wiki/SIMPLE_(instant_messaging_protocol)), allowing SMS to be sent using the extended SIP method; MESSAGE, natively. Still many [Internet Telephony Service Providers](https://en.wikipedia.org/wiki/Internet_telephony_service_provider) (ITSP) does not offer SIMPLE but instead sends and receives SMS using a web [API](https://en.wikipedia.org/wiki/Application_programming_interface) based on [HTTP](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol) requests. This leaves Asterisk without a mechanisms to exchange SMS externally. + +The WebSMS service bridges this limitation, with the help of two components. One, `websmsd`, waits for incoming SMS to be sent from your ITSP and once received, forward it to Asterisk. The other, `websms`, is used by Asterisk to send outgoing SMS to your ITSP. + +## Operation + +Asterisk natively handles SMS in between soft-phones using the [SIMPLE](https://en.wikipedia.org/wiki/SIMPLE_(instant_messaging_protocol)) protocol. When SMS is sent out to your ITSP Asterisk it uses an utility, `websms`, to send a HTTP [POST](https://en.wikipedia.org/wiki/POST_(HTTP)) request, containing the extension number, caller id and the message text, to the ITSP web [API](https://en.wikipedia.org/wiki/Application_programming_interface). Normally this request need to be authenticated using credentials provided by the ITSP. + +The `websmsd` client listens for HTTP POST request which your ITSP will issue when there is an incoming SMS. The request includes the extension number, caller id and the message text. Once received, this message is placed in the Asterisk call queue, using a [call file](https://wiki.asterisk.org/wiki/display/AST/Asterisk+Call+FIles). Asterisk will pick up the queued message and forward it to the relevant soft-phone using the SIMPLE protocol. For this to work you need to provide your ITSP with the URL to the `websmsd` client. + +### Selection of ITSP + +Not all ITSP offer [virtual numbers (DID)](https://en.wikipedia.org/wiki/Virtual_number) which can send and receive SMS, in the region you are interested in. So it might be a good idea to spend some time investigating what is available. + +### Emoticons and encoding + +Modern phones support the [Unicode](https://en.wikipedia.org/wiki/Universal_Coded_Character_Set) [UTF-8](http://www.utf-8.com/) and the GSM (7-bit) character encodings. Unicode characters used in SMS are 2 bytes (16-bits) or 4 bytes (32-bits) long and since length of an SMS message is limited to 140 bytes (1120 bits) the number of charters that can be sent in one SMS will depend on what encoding is used. If Unicode is used 70 charters can be sent in one SMS. The original GSM encoding uses 7-bit encoding allowing 160 charters. + +Most emoticons are encoded using 4 bytes reducing message length further. Another consideration is that not all ITSP has implemented an API supporting the full Unicode character range, making sending or receiving messages including emoticons difficult. + +### Reverse proxy + +I some scenarios it can be beneficial to use a [reverse proxy](https://en.wikipedia.org/wiki/Reverse_proxy) like [traefik](https://containo.us/traefik/), which is also providing [HTTPS](https://en.wikipedia.org/wiki/HTTPS), to route the HTTP(S) requests to the `websmsd` client. + +## Configuration + +Some functions of WebSMS are configurable by using a configuration file; `websms.conf`. Typically this file need to include the details of your account with the ITSP. The configuration file has three sections, they are: `[websms]` configuring outgoing SMS to the ITSP, `[websmsd]` configuring incoming SMS from the ITSP, and `[astqueue]` configuring the call queue, using call files, where incoming SMS are placed so that Asterisk can pick them up. + +| File name | Description | +| ----------- | ------------------------------------------------------ | +| websms.conf | Configurations which are unique to the WebSMS services | +### HTTP request header keys + +ITSPs have implemented their SMS API a little differently. Study the ITSP documentation and configure the `key_to`, `key_from` and `key_body` appropriately. + +```ini +key_to = To +key_from = From +key_body = Body +``` + +### Outgoing authentication method + +Most ITSP requires `websms` to authenticate when sending outgoing SMS via their API. When you set up an account with the ITSP they will provide you with the appropriate user/id and password/secret. + +```ini +[websms] +url_host = https://api.example.com +url_path = /sms/send/ +auth_user = id +auth_secret = secret +auth_method = basic +``` + +Not all ITSP use the same authentication method. +Currently there is support for: `none`, `plain`, `basic` and `zadarma`. + +#### `none` + +The POST request is sent without any authentication data. + +#### `plain` + +The `plain` method uses the parameters `key_user` and `key_secret` in addition to `auth_user` and `auth_secret`. +These are used to add the key-value pairs `:` and `:` to the POST request. + +#### `basic` + +[Basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication), +is a method for an [HTTP user agent](https://en.wikipedia.org/wiki/User_agent) (here `websms`) to provide a [user name](https://en.wikipedia.org/wiki/User_name) and [password](https://en.wikipedia.org/wiki/Password) when making a request. In basic HTTP authentication, a request contains a header field in the form of `Authorization: Basic `, where credentials is the [base64](https://en.wikipedia.org/wiki/Base64) encoding of id and password joined by a single colon `:`. + +When using the `basic` authentication method, it is not important how the full URL is separated into `url_host` and `url_path`. + +#### `zadarma` + +The ITSP [Zadarma](https://zadarma.com/en/support/api) uses an authentication method using a signature, ``, computed using the actual message and a secret key, to provide additional security. The request will use a header like: `Authorization: :`. + +The signature also uses the `url_path` part of the full request URL. To accommodate this scheme the full URL is separated into `url_host` and `url_path`. The actual request will use a URL which is the concatenation of `url_host` and `url_path`. + +### Incoming access control + +Since most ITSP does not implement incoming authentication, but operate using a limited range of IP addresses, we can filter incoming source addresses to achieve some access control. Use `remt_addr` to limit incoming access using comma separated address ranges in [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) format. By default any source addresses is permitted. + +When `websms` operates behind a reverse proxy we need to trust that the proxy reports the original source addresses. Use `prox_addr` to indicate the addresses of your trusted proxies using comma separated address ranges in [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) format. Often proxies sends the original source address in the header `HTTP_X_FORWARDED_FOR`. + +```ini +[websmsd] +remt_addr = 185.45.152.42,3.104.90.0/24,3.1.77.0/24 +prox_addr = 172.16.0.0/12,192.168.0.0/16 +prox_header = HTTP_X_FORWARDED_FOR +``` + +### Quirks + +Despite the API of different ITSP all serve a similar purpose, they all differ somewhat. To allow for this the WebSMS behavior can be modified to accommodate some of such peculiarities. + +#### Outgoing response check + +Some API respond with a status message to the HTTP request that we send, which can be used to check if the message was sent successfully. We can configure WebSMS to check if the response include the expected "key=value" pair. For example; `resp_check = "status=success"` + +#### Outgoing number format + +While most API accept any number format, some don't. We can omit the leading "+" in international numbers, by defining `val_numform = "E164"`. + +#### Outgoing character encoding + +SIP is a text-based protocol and uses the UTF-8 charset ([RFC 2279](https://tools.ietf.org/html/rfc2279)) and consequently also the message body of the MESSAGE method ([RFC 3261](https://tools.ietf.org/html/rfc3261)). UTF-8 is a multi-byte encoding able to encode the whole Unicode charset. An encoded character takes between 1 and 4 bytes. 2 bytes are sufficient to cover the code point range (U+0000, U+FFFF) called BMP (Basic Multilingual Plane). Most emoticons are non-BMP characters. To cover the complete BMP and the non-BMP (U+10000, U+10FFFF) range 4 bytes are needed. UCS-2 is an Unicode encoding limited to BMP characters. + +Many API supports the full range of Unicode character encoding, but some do not. In case the API only support UCS-2, it might be required to force WebSMS to use it and thereby limit the Unicode character range to BNP (U+0000, U+FFFF). This is achieved by defining `val_unicode = UCS-2`. + +There are APIs that supports the full range but needs an additional key-value pair in the HTTP request data to handle non-BMP characters. When defining `val_unicode = "key=value"` the key-value pair `key:value` is added to the request data when the message body include non-BMP characters. + +#### Outgoing static key-value pairs + +Sometimes your ITSP need some static key-value pairs in the HTTP request data that WebSMS does not provide. +In such case you can inject them using `val_static`. The syntax is; `val_static = "key1=value1,key2=value2`. + +#### Incoming echo + +Some API test that it can access your WebSMS web server, by sending a special HTTP request and expecting the response to echo a key value. Configure such echo response by defining the HTTP request key used by the API. For example `key_echo = "zd_echo"`. + +#### Incoming response + +Some API expects a specific response when sending a HTTP request to know that the transfer was successful. The response to incoming SMS is configured by using `resp_ack`. For example ` resp_ack = ""`. + +### Call queue contexts + +When using the PrivateDial dial-plan (extensions.conf), which has integrated the WebSMS service, the proper contexts are: + +```ini +[astqueue] +channel_context = dp_entry_answer +context = dp_entry_text_in +``` + +### Configuring WebSMS, websms.conf + +The WebSMS configuration is kept in `websms.conf`. This file is parsed by [PHP](https://secure.php.net/manual/en/function.parse-ini-file.php), which luckily, accepts a syntax similar to Asterisk's configuration files. +One difference is that the strings, "yes", "no", "true", "false" and "null" have to be within quotation marks otherwise they will be interpreted as Boolean by the PHP parser. In the table below some key names end with []. The square brackets are not part pf the actual key name, instead they indicate that the key can hold multiple values allowing more than one SMS API interface to be configured. + +| Section | Key | Default | Format | Description | +| ---------- | --------------- | ---------------------------- | ------- | ------------------------------------------------------------ | +| [websms] | auth_method [] | basic | string | Authentication method to use. | +| [websms] | auth_secret [] | | string | Authentication password/secret. | +| [websms] | auth_user [] | | string | Authentication user/id. | +| [websms] | key_body [] | Body | string | HTTP POST key name holding the SMS message. | +| [websms] | key_from [] | From | string | HTTP POST key name holding SMS originating phone number. | +| [websms] | key_secret [] | | string | HTTP POST key name holding password/secret with auth_method=plain. | +| [websms] | key_to [] | To | string | HTTP POST key name holding SMS destination phone number. | +| [websms] | key_user [] | | string | HTTP POST key name holding user/id with auth_method=plain. | +| [websms] | resp_check [] | | string | HTTP POST key=value to check, eg "status=success". | +| [websms] | url_host [] | http://localhost | URL | Scheme and host of the ITSP SMS API, eg https://api.example.com | +| [websms] | url_path [] | / | URL | Path of the ITSP SMS API, eg /sms/send/ | +| [websms] | val_numform [] | | string | Number format to use, eg "E164" will omit the leading "+" in international numbers. | +| [websms] | val_static [] | | string | Add key-value pairs, eg "key1=value1,key2=value2 | +| [websms] | val_unicode [] | | string | Set to "UCS-2" to limit Unicode characters to U+FFFF. Use "key=value" to add key-value pair when non-BMP chareters present. | +| [websmsd] | key_body [] | Body | string | HTTP POST key name holding the SMS message. | +| [websmsd] | key_echo [] | | string | Some ITSP test that the client respond by expecting it echoing the value in this key, eg "zd_echo". | +| [websmsd] | key_from [] | From | string | HTTP POST key name holding SMS origination phone number. | +| [websmsd] | key_to [] | To | string | HTTP POST key name holding SMS destination phone number. | +| [websmsd] | prox_addr | 172.16.0.0/12,192.168.0.0/16 | CIDR | Trust "prox_header" from these IPs, eg 10.0.0.0/8 | +| [websmsd] | prox_header | HTTP_X_FORWARDED_FOR | string | Behind a proxy this header hold the original client address. | +| [websmsd] | remt_addr [] | | CIDR | If defined, only listed addresses are allowed, eg 185.45.152.42,3.104.90.0/24,3.1.77.0/24 | +| [websmsd] | resp_ack [] | | string | Report success like this, eg, "". | +| [websmsd] | url_path [] | | string | If defined, only listed URL paths are allowed, eg /,/mywebhook/1. URIs must start with a "/". | +| [astqueue] | archive | no | string | Use "yes" to save call file to /var/spool/asterisk/outgoing_done | +| [astqueue] | channel_context | default | string | Dialplan context to answer the call, ie set up the channel. | +| [astqueue] | context | default | string | Dialplan context to handle the SMS. | +| [astqueue] | maxretries | 0 | integer | Number of retries before failing. 0 = don't retry if fails. | +| [astqueue] | message_encode | rfc3986 | string | Only single line allowed in call file so url-encoding message. | +| [astqueue] | outgoingdir | /var/spool/asterisk/outgoing | string | Directory where asterisk picks up call files. | +| [astqueue] | priority | 1 | integer | Dialplan priority to handle the SMS. | +| [astqueue] | retrytime | 300 | integer | How many seconds to wait before retry. | +| [astqueue] | stagingdir | /var/spool/asterisk/staging | string | Create call file here and then move to outgoing. | +| [astqueue] | waittime | 45 | integer | How many seconds to wait for an answer before the call fails. | + +### Default configuration + +If the Asterisk configuration directory is empty, default configuration files will be copied there at container startup. The one relevant here is `websms.conf`. + +```ini +[websms] +url_host = api.example.com +url_path = /sms/send/ +auth_user = user +auth_secret = secret + +[websmsd] + +[astqueue] +channel_context = dp_entry_answer +context = dp_entry_text_in +``` + +### Multiple interface configuration + +It is possible to define more than one SMS interface. This is useful when you subscribe to the service of more than one ITSP. For outgoing SMS, using `websms`, the interface is selected using a channel variable, `WEBSMS_INDEX`, you set on each PJSIP endpoint individually. For incoming SMS, using `websmsd`, the interface is selected based on the HTTP request parameters, `remt_addr` and/or `url_path`. + +The section [Default configuration](#default-configuration) contains an example of a configuration for a single interface, which we can use as a reference. Now lets look at a configuration, `websms.conf`, with two interfaces defined. + + ```ini +[websms] +url_host [api-1] = api.example1.com +url_path = /sms/send/ +auth_user [api-1] = user1 +auth_secret [api-1] = secret1 + +url_host [api-2] = api.example2.com +auth_user [api-2] = user2 +auth_secret [api-2] = secret2 + +[websmsd] +remt_addr [api-1] = 1.2.3.4/24 +url_path [api-1] = /incomming1 + +remt_addr [api-2] = 5.6.7.8,5.6.7.9 +url_path [api-2] = /incomming2 +key_body [api-2] = text + ``` + +As can be seen, parameters that are common between configurations does not need to be specified more than once, see for example the parameter `url_path` above. If a parameter is defined, using square brackets, but not for all interfaces, the default value will be used for the interfaces not defined. + +#### Multiple outgoing interface configurations + +The channel variable, `WEBSMS_INDEX`, needs to match one of the indexes used in the `[websms]` section. Lets look at an example snippet of `pjsip_wizard.conf` + +```ini +[john.doe](w_term:mydoe) +hint_exten = +12025550160 +endpoint/set_var = WEBSMS_INDEX=api-1 + +[jane.doe](w_term:mydoe) +hint_exten = +12025550183 +endpoint/set_var = WEBSMS_INDEX=api-2 +``` + +Here the endpoint `john.doe` will use the `api-1` configuration for outgoing SMS, whereas `jane.doe` will use `api-2`. + +#### Multiple incoming interface configurations + +For incoming SMS either the `remt_addr` and/or the `url_path` parameter needs to be defined, using square brackets, for each individual interface, if more than one is used. WebSMS matches these parameters for incoming requests to figure out which configuration to use. + +Note that, the parameters `prox_addr` and `prox_header` can *only* have a single definition, i.e. *no* square brackets, since they are used before the incoming request has been analyzed and the interface is therefore not yet know. + +It is not necessary to explicitly name the index in the `[websmsd]` section. If the index is omitted, the order of definitions will be important. To exemplify, this `[websmsd]` configuration is equivalent to the one above. + +```ini +[websmsd] +remt_addr [] = 1.2.3.4/24 +url_path [] = /incomming1 +remt_addr [] = 5.6.7.8,5.6.7.9 +url_path [] = /incomming2 +key_body [] = text +``` + +## Environment variables + +WebSMS is configured using configuration files. Still, there one environmental variable that influence the behavior of WebSMS; `WEBSMSD_PORT`. + +#### `WEBSMSD_PORT` + +WebSMS uses the PHP integrated web server. The environment variable `WEBSMSD_PORT=80` determinate which port the web server listens to. If `WEBSMSD_PORT` is undefined or non-numeric the PHP web server is disabled and, consequently, WebSMS too. Disabling the web server might be desired in scenarios when the container runs in host mode and there are other services running on the host blocking ports of concern. + +## Implementation + +implementing a PHP client script, which sends HTTP SMS requests, and a server that listens for HTTP POST request form your ITSP. + +Currently there can only be one WebSMS configuration, so it is not possible to send or receive SMS from more than one ITSP. + +### websms.php sending SMS to ITSP + +The function of `websms.php` in the SMS data flow is to transfer the message out of Asterisk onto the system of the ITSP. The underlying mechanism for this is a HTTP(S) request executed using [cURL](https://curl.haxx.se/). Admittedly, since Asterisk comes with integrated support for cURL using [libcurl](https://curl.haxx.se/libcurl/) it would be possible to implement the `websms` functionality without of going the route of calling a PHP script. The main motivation of `websms` is therefore "ease of use" since it can better leverage the companion function `websmsd`. + +To describe the data flow we walk trough an example where a soft-phone (endpoint) user sends a SMS to a destination outside of the PBX. The endpoint sends a SIP MESSAGE request [RFC3428](https://tools.ietf.org/html/rfc3428) to Asterisk and a [channel](https://wiki.asterisk.org/wiki/display/AST/Channels) is set up and placed in the dial-plan. The channel variables include the, `EXTEN`, `MESSAGE(to)`, `MESSAGE(from)`, and `MESSAGE(body)`. The external destination is identified in the dial-plan and `websms.php` is call via [Asterisk Gateway Interface (AGI)](https://wiki.asterisk.org/wiki/pages/viewpage.action?pageId=32375589) in the dial-plan (extensions.conf): + +```bash +same = n,AGI(websms.php,${EXTEN},${MESSAGE(from)},${QUOTE(${MESSAGE(body)})},${WEBSMS_INDEX}) +``` + +The `MESSAGE(body)` needs to be quoted since it can include special characters. With the provided arguments `websms.php` sends an authenticated HTTP request to the API of ITSP who will continue forward the SMS to its final destination. + +The payload of the HTTP request might look like this: + +```json +{"to":"+12025550183","from":"+12025550160","body":"Outgoing message!"} +``` + +For testing purposes, you can use `websms.php` to send a SMS from the command line inside the container: + +```bash +/usr/share/php7/websms.php +12025550183 +12025550160 "Outgoing message!" +``` + +### websmsd.php receiving SMS from ITSP + +Using the PHP built-in web-server, the `websmsd.php` script listens to HTTP requests, representing incoming SMS, +from your ITSP. One such request is received a call file is generated, which will automatically be picked up by asterisk. + +The PHP built-in web-server is started by issuing this command: + +```bash +php -S 0.0.0.0:$WEBSMSD_PORT -t $DOCKER_PHP_DIR websmsd.php +``` +Now we describe the data flow of receiving a SMS from the ITSP for illustrative purposes. Assume that your ITSP receives a SMS addressed to your virtual number. Your ITSP forwards this SMS to your server by via its API which sends a HTTP request to the URL that you have registered with them and to which you have configured `websmsd.php` to listen to. The payload of such HTTP request might look like this: + +```json +{"to":"+12025550160","from":"+15017122661","body":"Incoming message!"} +``` + +`websmsd.php` forwards the received SMS data, contained in the HTTP payload, to Asterisk, allowing it to pass it on to the endpoint, that is the soft-phone, by using the call file mechanism that we will describe next. + +### Call files + +[Call files](http://the-asterisk-book.com/1.6/call-file.html) are like a shell script for Asterisk. A user or application writes a call file into the directory `/var/spool/asterisk/outgoing/` where Asterisk processes it immediately. The call file contains all parameters needed by Asterisk to set up a channel able to carry a call or a message. + +One practical limitation to consider in our case is that a message cannot span multiple lines in an Asterisk call file. To work +around that we encode ([RFC3986](https://tools.ietf.org/html/rfc3986), which obsolete [RFC2396](https://tools.ietf.org/html/rfc2396)) the message, including any special characters like line breaks it may contain. + +The structure of a [call file](https://wiki.asterisk.org/wiki/display/AST/Asterisk+Call+FIles) is illustrated by the example below, which includes a encoded MESSAGE(body). +```ini +Channel: Local/+12025550160@dp_entry_answer +CallerID: "" <+15017122661> +WaitTime: 45 +MaxRetries: 0 +RetryTime: 300 +Context: dp_entry_text_in +Extension: +12025550160 +Priority: 1 +Archive: yes +setvar: MESSAGE(to)=+12025550160 +setvar: MESSAGE(from)=+15017122661 +setvar: MESSAGE(body)=Incoming%20message%21. +setvar: MESSAGE_ENCODE=rfc3986 +``` + +To make sure Asterisk does not tries to read the call file before it is fully written,`websmsd.php`first writes to the file in a staging directory before it is moved to the directory where Asterisk pick it up. + +Once Asterisk pick up the call file it creates a channel and start to execute it according what is specified in the dial plan. In the dial plan, defined by `extensions.conf` the function [`MESSAGE()`](https://wiki.asterisk.org/wiki/display/AST/Asterisk+17+Function_MESSAGE) is used to access the SMS data. diff --git a/asterisk/docker-asterisk-0.9.9/src/websms/entry.d/50-websms-update-port b/asterisk/docker-asterisk-0.9.9/src/websms/entry.d/50-websms-update-port new file mode 100755 index 0000000..0b4251b --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/websms/entry.d/50-websms-update-port @@ -0,0 +1,15 @@ +#!/bin/sh +# +# 50-websms-update-port +# +# +# +source docker-common.sh + +if $(echo $WEBSMSD_PORT | grep -qE "^[0-9]+$"); then + dc_log 5 "websmsd will listen to port=$WEBSMSD_PORT." + docker-service.sh "-n websmsd php -S 0.0.0.0:$WEBSMSD_PORT -t $DOCKER_PHP_DIR websmsd.php" +else + dc_log 5 "websmsd will be disabled since there was no valid port=$WEBSMSD_PORT." + touch ${SVDIR}/websmsd/down +fi diff --git a/asterisk/docker-asterisk-0.9.9/src/websms/php/astqueue.class.inc b/asterisk/docker-asterisk-0.9.9/src/websms/php/astqueue.class.inc new file mode 100644 index 0000000..81e3f5a --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/websms/php/astqueue.class.inc @@ -0,0 +1,261 @@ + '/var/spool/asterisk/outgoing', + 'stagingdir' => '/var/spool/asterisk/staging', + 'filemode' => null, + 'fileowner' => null, + 'waittime' => 45, + 'maxretries' => 0, + 'retrytime' => 300, + 'archive' => 'no', + 'channel_context' => 'default', + 'context' => 'default', + 'priority' => 1, + 'message_encode' => 'rfc3986', + ]; + const CALLFILE_SYNTAX = [ + 'Channel' => 'channel', + 'CallerID' => 'callid', + 'WaitTime' => 'config', + 'MaxRetries' => 'config', + 'RetryTime' => 'config', + 'Account' => 'config', + 'Application' => 'config', + 'Data' => 'config', + 'Context' => 'config', + 'Extension' => 'to', + 'Priority' => 'config', + 'Archive' => 'config', + ]; + const CALLFILE_SETVAR = [ + 'MESSAGE(to)' => 'to', + 'MESSAGE(from)' => 'from', + 'MESSAGE(body)' => 'body', + 'MESSAGE_ENCODE' => 'config', + ]; + private $config; + public $debug = false; + public function __construct($config = null, array $optconfig = []) { + if (is_string($config) !== true) { + $config = self::DEFAULT_CONF_FILE; + } + $this->config['astqueue'] = self::DEFAULT_CONF_VALS; + if (file_exists($config) === true) { + $config_ini = parse_ini_file($config,true); + $this->config['astqueue'] = array_merge($this->config['astqueue'], + $config_ini['astqueue']); + } + foreach ($optconfig as $var => $val) { + $this->config['astqueue'][$var] = $val; + } + $this->mkdir($this->config['astqueue']['outgoingdir']); + $this->mkdir($this->config['astqueue']['stagingdir']); + } + /*-------------------------------------------------------------------------- + Generate call file with message + @param array $data, eg ['to'=>'+1...60','from'=>'+1...25','body'=>'Hello!'] + $data['to'] : The SMS destination + $data['from'] : The SMS originator + $data['body'] : The SMS message + @return boolean true if successful otherwise false + */ + public function text($data) { + if (isset($data['to']) && isset($data['from']) && isset($data['body'])) { + $lines = $this->gen_lines(Self::CALLFILE_SYNTAX,$data); + $lines .= $this->gen_lines(Self::CALLFILE_SETVAR,$data,true); + $basename = $this->gen_basename($data); + return $this->write($basename, $lines); + } else { + return false; + } + } + /*-------------------------------------------------------------------------- + Generate call file with call + @param string $exten callee phone number, eg '+12025550160' + @param string $callid caller phone number, eg '+12025550125' + @return boolean true if successful otherwise false + */ + public function call($exten,$callid) { + if (isset($exten) && isset($callid)) { + $data = ['to'=>$exten,'from'=>$callid]; + $lines = $this->gen_lines(Self::CALLFILE_SYNTAX,$message); + $basename = $this->gen_basename($data); + return $this->write($basename, $lines); + } else { + return false; + } + } + /*-------------------------------------------------------------------------- + @param array $syntax, eg ['Channel'=>'channel','CallerID'=>'callid',...] + @param array $data, eg ['to'=>'+1...60','from'=>'+1...25','body'=>'Hello!'] + @param boolean $setvar use setvar syntax if true + @return string lines + */ + private function gen_lines($syntax,$data,$setvar = false) { + $return = null; + $to = $data['to']; + $from = $data['from']; + $body = $data['body']; + foreach ($syntax as $key => $type) { + switch ($type) { + case 'to': + $return .= $this->gen_line($key,$to,$setvar); + break; + case 'from': + $return .= $this->gen_line($key,$from,$setvar); + break; + case 'body': + $return .= $this->gen_line($key,$this->gen_body($body),true); + break; + case 'channel': + $return .= $this->gen_line($key,$this->gen_channel($to)); + break; + case 'callid': + $return .= $this->gen_line($key,$this->gen_callid($from)); + break; + case 'config': + $return .= $this->gen_line($key,$this->gen_config($key),$setvar); + break; + } + } + return $return; + } + /*-------------------------------------------------------------------------- + @param string $key, eg 'archive' + @param string $value, eg 'yes' + @param boolean $setvar use setvar syntax if true + @return string or null, eg 'archive: yes' + */ + private function gen_line($key,$value,$setvar = false) { + if (!isset($key) || !isset($value)) return null; + if ($setvar) { + return sprintf('setvar: %s=%s', $key, $value).PHP_EOL; + } else { + return sprintf('%s: %s', $key, $value).PHP_EOL; + } + } + /*-------------------------------------------------------------------------- + Get config value + @param string $key, eg 'waittime' + @return mixed config value, eg 45 + */ + public function gen_config($key) { + $key_lower = strtolower($key); + if(array_key_exists($key_lower,$this->config['astqueue'])) { + return $this->config['astqueue'][$key_lower]; + } else { + return null; + } + } + /*-------------------------------------------------------------------------- + Generate channel string + @param string $exten callee phone number, eg '+12025550160' + @return string channel + */ + private function gen_channel($exten) { + return sprintf('Local/%s@%s',$exten,$this->config['astqueue']['channel_context']); + } + /*-------------------------------------------------------------------------- + Generate callid string + @param string $number caller phone number, eg '+12025550183' + @param string $display caller display, eg 'Jane Doe' + @return string callid, eg '"Jane Doe" <+12025550183>' + */ + private function gen_callid($number,$display = '') { + return sprintf('"%s" <%s>',$display,$number); + } + /*-------------------------------------------------------------------------- + Generate call file basename. + Format: ..<3 digit random>.call + @param array $data['to'] callee phone number, eg '+12025550160' + @return void + */ + private function gen_basename($data) { + return sprintf("%s.%d.%03d.call",$data['to'],time(),rand(0,999)); + } + /*-------------------------------------------------------------------------- + The message cannot span multiple lines in an Asterisk call file. To work + around that we encode the message (RFC3986, which supersedes RFC2396). + @param string $string to escape + @return string escaped string + */ + private function gen_body($string) { + if ($this->config['astqueue']['message_encode'] === 'rfc3986') { + return rawurlencode($string); + } else { + return $string; + } + } + /*-------------------------------------------------------------------------- + Create new call file in the staging directory. + Using staging directory to avoid Asterisk reading an unfinished file. + Move the call file to the outgoing directory, so that Asterisk pick it up. + @param string $basename + @param string $lines file contents + @return boolean true if successful otherwise false + */ + private function write($basename, $lines) { + $stagingfile = $this->config['astqueue']['stagingdir'].'/'.$basename; + $outgoingfile = $this->config['astqueue']['outgoingdir'].'/'.$basename; + if (file_put_contents($stagingfile,$lines) === false) { + trigger_error("unable to open call file ($stagingfile)", E_USER_WARNING); + return false; + } + if (rename($stagingfile, $outgoingfile) === false) { + trigger_error("unable to move file ($stagingfile) to file ($outgoingfile)", + E_USER_WARNING); + return false; + } + return true; + } + /*-------------------------------------------------------------------------- + @param string $dir full path to directory + @return void + */ + private function mkdir($dir) { + if (!is_dir($dir) && !mkdir($dir)) + trigger_error("unable create directory ($dir)", E_USER_WARNING); + } + /*-------------------------------------------------------------------------- + NOT WORKING DUE TO PHP NOT HAVING ROOT ASSESS + */ + private function chmod() { + $outgoingfile = $this->config['astqueue']['outgoingdir'].'/'.$this->name; + if (!empty($this->config['astqueue']['filemode'])) { + chmod($outgoingfile, octdec($this->config['astqueue']['filemode'])); + } + if (!empty($this->config['astqueue']['fileowner'])) { + chmod($outgoingfile, chown($this->config['astqueue']['fileowner'])); + } + } + /*-------------------------------------------------------------------------- + Print variable if $debug or $this->debug is true + @param mixed $var + @param boolean $debug + @return void + */ + public function debug($var, $debug = false) { + if($debug || $this->debug) { + var_dump($var); + } + } +} +?> diff --git a/asterisk/docker-asterisk-0.9.9/src/websms/php/websms.class.inc b/asterisk/docker-asterisk-0.9.9/src/websms/php/websms.class.inc new file mode 100644 index 0000000..adeadf1 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/websms/php/websms.class.inc @@ -0,0 +1,599 @@ + + listen() + permitted() + echo() + post_mess($post) + answer($status) + + + + query($args) + args_mess($args) + curl_init() + curl_data($post) + curl_auth($post) + curl_send() + check($response) +*/ +class Websms { + const DEFAULT_CONF_FILE = '/etc/asterisk/websms.conf'; + const DEFAULT_CONF_VALS = [ + 'websms' => [ + 'auth_method' => "basic", + 'auth_secret' => null, + 'auth_user' => null, + 'key_body' => "Body", + 'key_from' => "From", + 'key_secret' => null, + 'key_to' => "To", + 'key_user' => null, + 'resp_check' => null, + 'url_host' => "http://localhost", + 'url_path' => "/", + 'val_numform' => null, + 'val_static' => null, + 'val_unicode' => null, + ], + 'websmsd' => [ + 'key_body' => "Body", + 'key_echo' => null, + 'key_from' => "From", + 'key_to' => "To", + 'prox_addr' => "172.16.0.0/12,192.168.0.0/16", + 'prox_header' => "HTTP_X_FORWARDED_FOR", + 'remt_addr' => null, + 'resp_ack' => "", + 'url_path' => null, + ] + ]; + private $config; + public $index; + private $curl; + public $debug = false; + public function __construct($config = null, array $optconfig = []) { + if (is_string($config) !== true) { + $config = self::DEFAULT_CONF_FILE; + } + $this->config = self::DEFAULT_CONF_VALS; + if (file_exists($config) === true) { + $config_ini = parse_ini_file($config,true); + if (!empty($config_ini['websmsd'])) + $this->config['websmsd'] = array_merge($this->config['websmsd'], + $config_ini['websmsd']); + if (!empty($config_ini['websms'])) + $this->config['websms'] = array_merge($this->config['websms'], + $config_ini['websms']); + } + foreach ($optconfig as $var => $val) { + $this->config['websms'][$var] = $val; + } + } + /*-------------------------------------------------------------------------- + Read the post header data. + @return mixed array message or boolean false + */ + public function rx_query() { + if ($this->identify_remote()) { + $this->if_echo_exit(); + return $this->message_data(); + } else return false; + } + /*-------------------------------------------------------------------------- + Respond with a status message. + @param Boolean $status + @param array $message to, from, and body. + @return void + */ + public function ack_query($status = true, $message) { + if ($status) { + trigger_error(sprintf( + "Inbound SMS accepted, to (%s) from (%s)", $message['to'], + $message['from']), E_USER_NOTICE); + echo $this->config('websmsd','resp_ack'); + } + } + /*-------------------------------------------------------------------------- + Send SMS HTTP POST query. We require 3 arguments; to, from, body. + args[0] is set to script name so drop this. + + Outline + Parse arguments. + Build http POST query. + Setup curl for POST query. + Setup curl's authentication method. + Send POST query. + Check response. + */ + public function tx_query($args) { + unset($args[0]); + $query_data = $this->query_data($args); + if (!empty($query_data)) { + $this->val_unicode($query_data); + $this->val_numform($query_data); + $this->val_static($query_data); + $this->curl_init(); + $this->curl_auth($query_data); + $this->curl_data($query_data); + $resp_data = $this->curl_send(); + return $this->resp_check($resp_data); + } else { + return false; + } + } + /*-------------------------------------------------------------------------- + If remt_addr is set, match remote host and request uri, set index. + If remt_addr isn't set but uri is, match request uri, set index. + @return Boolean true if matched, otherwise false + */ + private function identify_remote() { + $allow = true; + $match_addr = $this->config('websmsd','remt_addr',true); + $remt_addr = $this->remt_addr(); + $request_uri = $_SERVER['REQUEST_URI']; + if(isset($match_addr)) { + $allow = false; + if (is_array($match_addr)) { + foreach ($match_addr as $index => $value) { + if($this->match_cidr($remt_addr,$value)) { + $allow = true; + $this->index = $index; + } + } + } else { + if($this->match_cidr($remt_addr,$match_addr)) $allow = true; + } + if($allow) trigger_error( + sprintf("REMOTE_ADDR (%s) is allowed, using index (%s)", + $remt_addr, $this->index), E_USER_NOTICE); + else trigger_error( + sprintf("REMOTE_ADDR (%s) is NOT allowed", + $remt_addr), E_USER_WARNING); + if($this->debug) trigger_error(file_get_contents('php://input') . print_r($_SERVER, TRUE)); + } + /* + Wait until now to call $this->config('websmsd','uri') since + $this->index might have been set above. + */ + $match_uri = $this->config('websmsd','url_path',true); + if($allow && isset($match_uri)) { + $allow = false; + if (is_array($match_uri)) { + foreach ($match_uri as $index => $value) { + if($this->match_uri($value)) { + $allow = true; + $this->index = $index; + } + } + } else { + if($this->match_uri($match_uri)) $allow = true; + } + if($allow) trigger_error( + sprintf("REQUEST_URI (%s) is allowed, using index (%s)", + $request_uri, $this->index), E_USER_NOTICE); + else trigger_error( + sprintf("REQUEST_URI (%s) is NOT allowed", + $request_uri), E_USER_WARNING); + } + return $allow; + } + /*-------------------------------------------------------------------------- + Respond to echo requests. + The API of some ITSP, eg Zadarma, test the web server by sending an echo + request. Let's respond and exit if we detect a echo request. + */ + private function if_echo_exit() { + if (!empty($this->config('websmsd','key_echo')) + && isset($_GET[$this->config('websmsd','key_echo')])) { + trigger_error('Received echo request ('.$_GET[$this->config('websmsd','key_echo')].')', E_USER_NOTICE); + exit($_GET[$this->config('websmsd','key_echo')]); + } + } + /*-------------------------------------------------------------------------- + Evaluates POST request data and returns $message. Parameters are + json decoded and searched recursively. + Use $_POST since file_get_contents("php://input") cannot handle multipart/form-data + @return array $message to, from, and body. + */ + private function message_data() { + $post_data = $_POST; + $message = []; + if (empty($post_data)) { + trigger_error("No POST header data", E_USER_WARNING); + return false; + } else { + if($this->debug) { + trigger_error(sprintf("POST data (%s)",json_encode($post_data))); + } + } + array_walk_recursive($post_data, function(&$val) { + $val_json = json_decode($val,true); + if (!empty($val_json)) $val = $val_json; + }); + array_walk_recursive($post_data, function($val,$key) use (&$message) { + if ($key === $this->config('websmsd','key_to')) $message['to'] = $val; + if ($key === $this->config('websmsd','key_from')) $message['from'] = $val; + if ($key === $this->config('websmsd','key_body')) $message['body'] = $val; + }); + if (empty($message['body'])) $message['body'] = ''; + if (empty($message['to']) || empty($message['from'])) { + trigger_error(sprintf("Did not get all required POST data (%s) message (%s)", + json_encode($post_data),json_encode($message)), E_USER_WARNING); + } + return $message; + } + /*-------------------------------------------------------------------------- + Initially assume 'REMOTE_ADDR' is the original IP of the HTTP client. But if + it is a 'prox_addr' then trust that 'prox_header' hold the real IP of the + client instead. + @return string $remt_addr + */ + private function remt_addr() { + $remt_addr = $_SERVER['REMOTE_ADDR']; + $prox_addr = $this->config('websmsd','prox_addr'); + $prox_header = $this->config('websmsd','prox_header'); + if (!empty($prox_addr) && !empty($prox_header) && + $this->match_cidr($remt_addr,$prox_addr)) { + $header_addr = @$_SERVER[$prox_header]; + if (isset($header_addr)) { + $remt_addr = $header_addr; + } else { + trigger_error( + sprintf("REMOTE_ADDR (%s) matches proxy (%s) but there is no header (%s)", + $remt_addr, $prox_addr, $prox_header), E_USER_WARNING); + } + } + return $remt_addr; + } + /*-------------------------------------------------------------------------- + Compare each uri (comma separated) with the REQUEST_URI + @param string $csv_uris uris to test eg, /index.htm,/index.html + @return Boolean true if $saddr is permitted otherwise false + */ + private function match_uri($csv_uris) { + $request_uri = $_SERVER['REQUEST_URI']; + $match_uris = explode(',',$csv_uris); + foreach ($match_uris as $match_uri) { + if(strcmp($match_uri,$request_uri) === 0) return true; + } + return false; + } + /*-------------------------------------------------------------------------- + @param string $ip addr to test eg, 216.245.217.2 + @param string $csvcidrs comma separated list of CIDR ranges + eg, 185.45.152.42,3.104.90.0/24,3.1.77.0/24 + @return Boolean true if $ip matches any range in $csvcidrs + */ + public function match_cidr($ip,$csvcidrs) { + $cidrs = explode(',',$csvcidrs); + foreach ($cidrs as $cidr) { + $blknmask = explode('/',$cidr); + $blk = $blknmask[0]; + if (isset($blknmask[1])) { + $mask = $blknmask[1]; + } else { + $mask = 32; + } + $blkbin = ip2long($blk) >> (32 - $mask); + $ipbin = ip2long($ip) >> (32 - $mask); + if ($ipbin === $blkbin) return true; + } + return false; + } + /*-------------------------------------------------------------------------- + Receive an additional header "Signature", + $signatureTest = base64_encode(hash_hmac('sha1', $_POST['result'], API_SECRET)); + @param array $post HTTP POST + @return Boolean true if HTTP request was verified + */ + private function verify($post) { + $auth_method = $this->config('websmsd','auth_method'); + $auth_secret = $this->config('websmsd','auth_secret'); + switch ($auth_method) { + case '': + return true; + break; + case 'zadarma': + $result = $post['result']; + $sign = $post['Signature']; + $sign_expected = base64_encode(hash_hmac('sha1', $result, $auth_secret)); + return ($sign === $sign_expected); + break; + default: + trigger_error("Unknown method (auth_method=$auth_method)", E_USER_WARNING); + return true; + break; + } + } + /*-------------------------------------------------------------------------- + Parse arguments. + We require 3 arguments; to, from, body. + OR 4 arguments; to, from, body, index. + @param array $args arguments + @return array $query_data or false + */ + private function query_data($args) { + switch (count($args)) { + case 4: + $index = $args[4]; + if(strlen($index) > 0) $this->index = $index; + case 3: + $query_data = [ + $this->config('websms','key_to') => $args[1], + $this->config('websms','key_from') => $args[2], + $this->config('websms','key_body') => $args[3], + ]; + return $query_data; + default: + $strings = implode(',',$args); + trigger_error("We did not get exactly 3 or 4 arguments; to, from, body [index] ($strings)", E_USER_WARNING); + return false; + } + } + /*-------------------------------------------------------------------------- + Sanitize telephone numbers. + @param array $query_data + @void + */ + private function val_numform(&$query_data) { + $key_to = $this->config('websms','key_to'); + $key_from = $this->config('websms','key_from'); + switch (strtolower($this->config('websms','val_numform'))) { + case 'no+': + case 'e164': + case 'e.164': + $query_data[$key_to] = preg_replace(['/^[+]/','/^00/'], '',$query_data[$key_to]); + $query_data[$key_from] = preg_replace(['/^[+]/','/^00/'], '',$query_data[$key_from]); + break; + case 'e.123': + default: + } + } + /*-------------------------------------------------------------------------- + Add key-value pairs in $query_data + @param array $query_data + @void + */ + private function val_static(&$query_data) { + $val_static = $this->config('websms','val_static'); + if (!empty($val_static)) { + $static_keyvals = explode(',',$val_static); + foreach ($static_keyvals as $static_keyval) { + if (strpos($static_keyval, '=') !== false) { + list($key, $val) = explode('=',$static_keyval); + $query_data[$key] = $val; + } + } + } + } + /*-------------------------------------------------------------------------- + Sanitize body, since some API only accept Unicode up to xFFFF BMP (UCS-2). + ucs-2: + Replace characters in SMP with the replacement character U+FFFD, when needed. + key=val: + If There is SMP characters add the provided key:val + otherwise: + Do nothing. + @param array $query_data + @void + */ + private function val_unicode(&$query_data) { + $val_unicode = $this->config('websms','val_unicode'); + $key_body = $this->config('websms','key_body'); + if (strpos($val_unicode, '=') !== false) { + list($key_code, $val_code) = explode('=',$val_unicode); + $val_unicode = 'key=val'; + } + switch (strtolower($val_unicode)) { + case 'ucs-2': + $query_data[$key_body] = preg_replace('/[\x{10000}-\x{10FFFF}]/u',"\u{FFFD}",$query_data[$key_body]); + break; + case 'key=val': + if (!empty(preg_grep("/[\x{10000}-\x{10FFFF}]/u",[$query_data[$key_body]]))) + $query_data[$key_code] = $val_code; + break; + case 'utf-8': + default: + } + } + /*-------------------------------------------------------------------------- + Init and setup curl for a POST query. + @return void + */ + private function curl_init() { + $url = $this->config('websms','url_host').$this->config('websms','url_path'); + $this->curl = curl_init($url); + curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($this->curl, CURLOPT_POST, true); + curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false); + } + /*-------------------------------------------------------------------------- + Generates a URL-encoded query string from the $query_data array provided, + and pass it on to curl. + @param array $query_data + @return string $query_string + */ + private function curl_data($query_data) { + ksort($query_data); + $this->debug($query_data); + $query_string = http_build_query($query_data); + curl_setopt($this->curl, CURLOPT_POSTFIELDS, $query_string); + return $query_string; + } + /*-------------------------------------------------------------------------- + Setup curl's authentication method. + Currently we support: + + 'basic' + basic access authentication, see, wikipedia.org/wiki/Basic_access_authentication, + with headers like: Authorization: Basic + + 'zadarma' + Zadarma's unique authentication method, see, zadarma.com/en/support/api, + with headers like: Authorization: : + @param array $query_data + @return void + */ + private function curl_auth(&$query_data) { + $auth_method = $this->config('websms','auth_method'); + $auth_user = $this->config('websms','auth_user'); + $auth_secret = $this->config('websms','auth_secret'); + $key_user = $this->config('websms','key_user'); + $key_secret = $this->config('websms','key_secret'); + $url_path = $this->config('websms','url_path'); + switch ($auth_method) { + case 'none': + break; + case 'plain': + if (!empty($key_user) && !empty($auth_user) && !empty($key_secret) && !empty($auth_secret)) { + $query_data[$key_user] = $auth_user; + $query_data[$key_secret] = $auth_secret; + } else trigger_error( + sprintf("Authorization method (%s) but not all needed parameters are defined",$auth_method), E_USER_WARNING); + break; + case 'basic': + if (!empty($auth_user) && !empty($auth_secret)) { + curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_setopt($this->curl, CURLOPT_USERPWD, "$auth_user:$auth_secret"); + } else trigger_error( + sprintf("Authorization method (%s) but not all needed parameters are defined",$auth_method), E_USER_WARNING); + break; + case 'zadarma': + if (!empty($auth_user) && !empty($auth_secret)) { + $query_string = $this->curl_data($query_data); + $signature = base64_encode(hash_hmac('sha1', $url_path . + $query_string . md5($query_string), $auth_secret)); + curl_setopt($this->curl, CURLOPT_HTTPHEADER, + array('Authorization: ' . $auth_user . ':' . $signature)); + } else trigger_error( + sprintf("Authorization method (%s) but not all needed parameters are defined",$auth_method), E_USER_WARNING); + break; + default: trigger_error( + sprintf("Unknown authorization method (auth_method=%s)",$auth_method), E_USER_WARNING); + } + } + /*-------------------------------------------------------------------------- + Send POST query, read response and close. + @return array $resp_data + */ + private function curl_send() { + $resp_json = curl_exec($this->curl); + if (!empty($resp_json)) { + $resp_data = json_decode($resp_json,true); + } else { + $resp_data = false; + trigger_error("Curl error: ".curl_error($this->curl)); + } + $curl_info = curl_getinfo($this->curl); + curl_close($this->curl); + //$this->debug($curl_info); + $this->debug($resp_json); + return $resp_data; + } + /*-------------------------------------------------------------------------- + Check response and set exit code accordingly. + the response check is controlled by the variable resp_check. It can be: + = null\""; No check, we will always exit with status true + = "key=value" If value of key in response is equal to value exit true otherwise false + = "/pattern/"; If pattern matches response exit with status true otherwise false + { + "status":"success", + "messages":1, + "cost":0.24, + "currency":"USD" + } + @param array $resp_data + @return Boolean true if resp_check matches, otherwize false + */ + private function resp_check($resp_data) { + $resp_check = $this->config('websms','resp_check'); + $url_host = $this->config('websms','url_host'); + $auth_user = $this->config('websms','auth_user'); + if (empty($resp_data)) return false; + if (!empty($resp_check)) { + if (strpos($resp_check, '=') !== false) { // "key=value" + list($test_key, $test_value) = explode('=',$resp_check); + // test hierarchically + array_walk_recursive($resp_data, function($val,$key) use (&$resp_value,$test_key) { + if ($key === $test_key) $resp_value = $val; + }); + if ($resp_value !== $test_value) { + trigger_error(sprintf("Called (%s) but return did not match (%s = %s != %s)", + $url_host,$test_key,$resp_value,$test_value), E_USER_WARNING); + trigger_error(sprintf("Response was: %s",json_encode($resp_data))); + return false; + } + } else { // "/pattern/" + if (!preg_match($resp_check,$resp_data)) { + trigger_error(sprintf("Called (%s) but return did not match (%s != %s)", + $url_host,$resp_data,$resp_check), E_USER_WARNING); + trigger_error(sprintf("Response was: %s",json_encode($resp_data))); + return false; + } + } + trigger_error("Outbound SMS sent (host=$url_host,user=$auth_user) successfully", E_USER_NOTICE); + } else { + trigger_error("Outbound SMS sent (host=$url_host,user=$auth_user)", E_USER_NOTICE); + } + return true; + } + /*-------------------------------------------------------------------------- + Get configuration value, if $this->index is set pick that element in array + @param mixed $section + @param mixed $key + @param Boolean $allow_array + @return mixed $value or $array_of_values if $allow_array = true + */ + public function config($section, $key, $allow_array = false) { + $value = $this->config[$section][$key]; + $indices = $this->config_indices($section); + if (is_array($value)) { + if (isset($this->index)) { + if (array_key_exists($this->index,$value)) { + $value = $value[$this->index]; + } else { + $value = self::DEFAULT_CONF_VALS[$section][$key]; + if (!in_array($this->index,$indices)) trigger_error( + sprintf("Config ([%s] %s [%s]) missing; using default", + $section,$key,$this->index), E_USER_NOTICE); + } + } else { + if ($allow_array !== true) { + trigger_error( + sprintf("Config ([%s] %s) is array but index is not provided", + $section,$key), E_USER_ERROR); + $value = null; + } + } + } + return $value; + } + /*-------------------------------------------------------------------------- + */ + public function config_indices($section) { + $indices = []; + array_walk($this->config[$section], function($val,$key) use (&$indices) { + if(is_array($val)) + foreach($val as $key => $value) + if(!in_array($key, $indices)) + $indices[] = $key; + }); + return $indices; + } + /*-------------------------------------------------------------------------- + Print variable if $debug or $this->debug is true + @param mixed $var + @param boolean $debug + @return void + */ + public function debug($var, $debug = false) { + if($debug || $this->debug) { + var_dump($var); + } + } +} +?> diff --git a/asterisk/docker-asterisk-0.9.9/src/websms/php/websms.php b/asterisk/docker-asterisk-0.9.9/src/websms/php/websms.php new file mode 100755 index 0000000..fda5ae5 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/websms/php/websms.php @@ -0,0 +1,28 @@ +#!/usr/bin/env php +tx_query(@$argv)) { + $exit_code = 0; +} else { + $exit_code = 1; +} + +closelog(); +exit($exit_code); +?> diff --git a/asterisk/docker-asterisk-0.9.9/src/websms/php/websmsd.php b/asterisk/docker-asterisk-0.9.9/src/websms/php/websmsd.php new file mode 100644 index 0000000..b2f768c --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/src/websms/php/websmsd.php @@ -0,0 +1,34 @@ +rx_query(); +$status = $queue->text($message); +$sms->ack_query($status, $message); +?> diff --git a/asterisk/docker-asterisk-0.9.9/sub/module/phpami/.gitignore b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/.gitignore new file mode 100644 index 0000000..346b3ed --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/.gitignore @@ -0,0 +1,5 @@ +/composer.phar +/vendor +/bin +/.idea +/vbin diff --git a/asterisk/docker-asterisk-0.9.9/sub/module/phpami/LICENSE b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/LICENSE new file mode 100644 index 0000000..3b20440 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/LICENSE @@ -0,0 +1,458 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/asterisk/docker-asterisk-0.9.9/sub/module/phpami/README.md b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/README.md new file mode 100644 index 0000000..ce8d31c --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/README.md @@ -0,0 +1,58 @@ +# phpami +Asterisk Manager Interface (AMI) for PHP 5.4+ supporting legacy v1.4 to v13 with no thrills. + +This is a fork and update of the AMI portion of the now defunc [PHPAGI](http://phpagi.sourceforge.net/) PHP 4.4 project which has not been updated since 2010. + +We have kept the simplicity of a single class with command methods, adding a packagist entry and namespaces. This is a breaking change as class and method names have changed to follow modern standards, however they are a 1:1 mapping so updating your code should be straight forward. + +## Alternatives + +If you are dealing with only Asterisk v13+ servers, consider using [PAMI](http://marcelog.github.io/PAMI/) instead, which uses modern design paterns with observer-listener pattern. It no longer supports legacy Asterisk versions like v1.4 however. It may also see less development than the [NAMI](http://marcelog.github.io/Nami/) library for NodeJS. + +## Updates + +The project is considered in a usable state and feature complete. + +This project is used in corporate applications. As such, the authors are unlikely to update it on a regular basis, but instead when the corporate applications that use it run into problems. You should expect updates in the 5-10yr range. + +Issues and PRs will be monitored, and we will continue to work with the community to provide updates as they are contributed. + +## Installing via Composer + +The recommended way to install PHPAMI is through +[Composer](http://getcomposer.org). + +```bash +# Install Composer +curl -sS https://getcomposer.org/installer | php +``` + +Next, run the Composer command to install the latest stable version: + +```bash +composer.phar require ofbeaton/phpami +``` + +After installing, you can now use it in your code: + +```php + $ami = new \PHPAMI\Ami(); + if ($ami->connect('localhost:5038', 'myuser', 'mysecret', 'off') === false) { + throw new \RuntimeException('Could not connect to Asterisk Management Interface.'); + } + + // // if you have a looping of command function + // // set allowTimeout flag to true + // $ami->allowTimeout(); + + // $result contains the output from the command + $result = $ami->command('core show channels'); + + $ami->disconnect(); +``` + +## License + +This software is distributed under the LGPL 2.1 License. Please see [License file](LICENSE) for more information. + +This library is a fork of the now defunc [PHPAGI](http://phpagi.sourceforge.net/) project by Matthew Asham. See [Fork release](https://github.com/ofbeaton/phpami/releases/tag/0.1) for more details. diff --git a/asterisk/docker-asterisk-0.9.9/sub/module/phpami/composer.json b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/composer.json new file mode 100644 index 0000000..11cedf2 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/composer.json @@ -0,0 +1,54 @@ +{ + "name": "ofbeaton/phpami", + "description": "Asterisk Manager Interface (AMI) for PHP 5.4+ supporting legacy v1.4 to v13 with no thrills.", + "keywords": [ + "Asterisk", + "astx", + "AMI", + "phpami", + "phpagi", + "pami", + "pagi" + ], + "homepage": "https://github.com/ofbeaton/phpami", + "license": "LGPL-2.1-only", + "authors": [ + { + "name": "Finlay Beaton", + "email": "ofbeaton@gmail.com" + }, + { + "name": "Phpami Community", + "homepage": "https://github.com/ofbeaton/phpami/graphs/contributors" + }, + { + "name": "PHPAGI Community (pre-fork)", + "homepage": "http://sourceforge.net/p/phpagi/_members/" + } + ], + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "ofbeaton/granite-php": "^6.0", + "squizlabs/php_codesniffer": "^3.4" + }, + "config": { + "bin-dir": "vbin" + }, + "autoload": { + "psr-4": { + "PHPAMI\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "PHPAMI\\Tests\\": "tests" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} diff --git a/asterisk/docker-asterisk-0.9.9/sub/module/phpami/composer.lock b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/composer.lock new file mode 100644 index 0000000..6a2fc15 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/composer.lock @@ -0,0 +1,126 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "4c85890cfd4b93685a90d1784f890253", + "packages": [], + "packages-dev": [ + { + "name": "ofbeaton/granite-php", + "version": "6.9.0", + "source": { + "type": "git", + "url": "https://github.com/ofbeaton/granite-php.git", + "reference": "1767dfb3dd7f9a0026c007cd68ad7ffeb51d4b82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ofbeaton/granite-php/zipball/1767dfb3dd7f9a0026c007cd68ad7ffeb51d4b82", + "reference": "1767dfb3dd7f9a0026c007cd68ad7ffeb51d4b82", + "shasum": "" + }, + "require-dev": { + "jakub-onderka/php-console-highlighter": "^0.4.0", + "jakub-onderka/php-parallel-lint": "^1.0", + "squizlabs/php_codesniffer": "^3.4" + }, + "suggest": { + "jakub-onderka/php-console-highlighter": "Highlight syntax for php-parallel-lint", + "jakub-onderka/php-parallel-lint": "speed up `php -l` check", + "squizlabs/php_codesniffer": "check and fix granite code style" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Finlay Beaton", + "email": "ofbeaton@gmail.com" + }, + { + "name": "Granite Community", + "homepage": "https://github.com/ofbeaton/granite-php/graphs/contributors" + } + ], + "description": "Opinionated PHP Coding Style enforcement for PHP", + "homepage": "https://github.com/ofbeaton/granite-php", + "keywords": [ + "Code style", + "Coding Style", + "PHP_CodeSniffer", + "code sniffer", + "lint" + ], + "time": "2019-03-21T21:17:59+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.4.2", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "b8a7362af1cc1aadb5bd36c3defc4dda2cf5f0a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/b8a7362af1cc1aadb5bd36c3defc4dda2cf5f0a8", + "reference": "b8a7362af1cc1aadb5bd36c3defc4dda2cf5f0a8", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2019-04-10T23:49:02+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.4.0" + }, + "platform-dev": [] +} diff --git a/asterisk/docker-asterisk-0.9.9/sub/module/phpami/phpcs.xml b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/phpcs.xml new file mode 100644 index 0000000..13abdf8 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/phpcs.xml @@ -0,0 +1,12 @@ + + + The default command line arguments + + src + + + + + + + diff --git a/asterisk/docker-asterisk-0.9.9/sub/module/phpami/phpcs/PHPAMI/ruleset.xml b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/phpcs/PHPAMI/ruleset.xml new file mode 100644 index 0000000..28ee9ff --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/phpcs/PHPAMI/ruleset.xml @@ -0,0 +1,7 @@ + + + The coding standard for the PHPAMI project. + + + + diff --git a/asterisk/docker-asterisk-0.9.9/sub/module/phpami/src/Ami.php b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/src/Ami.php new file mode 100644 index 0000000..db7cead --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/sub/module/phpami/src/Ami.php @@ -0,0 +1,1249 @@ + and others, PHPAGI (pre-fork) + * All Rights Reserved. + * + * This software is released under the terms of the GNU Lesser General Public License v2.1 + * A copy of which is available from http://www.gnu.org/copyleft/lesser.html + */ + +namespace PHPAMI; + +/** + * Asterisk Manager class + * + * @link http://www.voip-info.org/wiki-Asterisk+config+manager.conf + * @link http://www.voip-info.org/wiki-Asterisk+manager+API + * @example examples/sip_show_peer.php Get information about a sip peer + */ +class Ami +{ + /** + * Location of the asterisk directory. + */ + const AST_CONFIG_DIR = '/etc/asterisk/'; + + /** + * Default configuration file for PHPAMI, in the asterisk directory. + */ + const DEFAULT_PHPAMI_CONFIG = '/etc/asterisk/phpami.conf'; + + /** + * Default configuration file for PHPAGI, in the asterisk directory. + * + * Included for backwards compatibility with PHPAGI library. + */ + const DEFAULT_PHPAGI_CONFIG = '/etc/asterisk/phpagi.conf'; + + /** + * Log level. + */ + const LOG_FATAL = 0; + + /** + * Log level. + */ + const LOG_ERROR = 1; + + /** + * Log level. + */ + const LOG_WARN = 2; + + /** + * Log level. + */ + const LOG_INFO = 3; + + /** + * Log level. + */ + const LOG_DEBUG = 4; + + /** + * Log level. + */ + const LOG_TRACE = 5; + + /** + * Config variables + * + * @var array + */ + public $config; + + /** + * Socket + * + * @var resource|null + */ + public $socket = null; + + /** + * Server we are connected to + * + * @var string + */ + public $server; + + /** + * Port on the server we are connected to + * + * @var integer + */ + public $port; + + /** + * @var int Used in waitResponse function to prevent looping when true + */ + private $allowTimeout; + + /** + * Event Handlers + * + * @var array + */ + private $eventHandlers; + + /** + * Whether we're successfully logged in + * + * @var boolean + */ + private $loggedIn = false; + + /** + * @var int Log level. + */ + private $logLevel = self::LOG_ERROR; + + + /** + * Constructor + * + * @param string|array $config Name of the config file to parse. + * @param array $optconfig Array of configuration vars and vals, stuffed into $this->config['asmanager']. + */ + public function __construct($config = null, array $optconfig = []) + { + // load config + if (is_string($config) === true && file_exists($config) === true) { + $this->config = parse_ini_file($config, true); + } elseif (file_exists(self::DEFAULT_PHPAMI_CONFIG) === true) { + $this->config = parse_ini_file(self::DEFAULT_PHPAMI_CONFIG, true); + } elseif (file_exists(self::DEFAULT_PHPAGI_CONFIG) === true) { + $this->config = parse_ini_file(self::DEFAULT_PHPAGI_CONFIG, true); + } + + // If optconfig is specified, stuff vals and vars into 'asmanager' config array. + foreach ($optconfig as $var => $val) { + $this->config['asmanager'][$var] = $val; + } + + // add default values to config for uninitialized values + if (isset($this->config['asmanager']['server']) === false) { + $this->config['asmanager']['server'] = 'localhost'; + } + + if (isset($this->config['asmanager']['port']) === false) { + $this->config['asmanager']['port'] = 5038; + } + + if (isset($this->config['asmanager']['username']) === false) { + $this->config['asmanager']['username'] = 'phpagi'; + } + + if (isset($this->config['asmanager']['secret']) === false) { + $this->config['asmanager']['secret'] = 'phpagi'; + } + }//end __construct() + + + /** + * Send a request + * + * @param string $action To send. + * @param array $parameters To attach. + * + * @return array of parameters, empty if invalid socket resource + */ + public function sendRequest($action, array $parameters = []) + { + if (!is_resource($this->socket)) { + return []; + } + + $req = 'Action: '.$action."\r\n"; + foreach ($parameters as $var => $val) { + if (is_array($val) === true) { // only supported by Asterisk > 1.4 + foreach ($val as $k => $v) { + $req .= $var.': '.$k.'='.$v."\r\n"; + } + } else { + $req .= $var.': '.$val."\r\n"; + } + } + + $req .= "\r\n"; + fwrite($this->socket, $req); + $response = $this->waitResponse(); + + return $response; + }//end sendRequest() + + /** + * Set global allowTimeout flag + * it will prevent looping waitResponse function + * + * @param boolean $value + * @return void + */ + public function allowTimeout($value = true) + { + $this->allowTimeout = boolval($value); + }//end allowTimeout() + + /** + * Wait for a response + * + * If a request was just sent, this will return the response. + * Otherwise, it will loop forever, handling events. + * + * @param boolean $allowTimeout If the socket times out, return an empty array. + * + * @return array of parameters, empty on timeout or invalid socket resource + */ + public function waitResponse($allowTimeout = false) + { + if (!is_resource($this->socket)) { + return []; + } + + $allowTimeout = $this->allowTimeout ?: $allowTimeout; + + // make sure we haven't already timed out + $info = stream_get_meta_data($this->socket); + if (feof($this->socket) === true || $info['timed_out'] === true) { + return []; + } + + $timeout = false; + do { + $type = null; + $parameters = []; + + $buffer = trim(fgets($this->socket, 4096)); + while ($buffer !== false && $buffer !== '') { + $a = strpos($buffer, ':'); + if ($a !== false) { + if (count($parameters) === 0) { // first line in a response? + $type = strtolower(substr($buffer, 0, $a)); + if (substr($buffer, ($a + 2)) === 'Follows') { + // A follows response means there is a miltiline field that follows. + $parameters['data'] = ''; + $buff = fgets($this->socket, 4096); + $info = stream_get_meta_data($this->socket); + while (substr($buff, 0, 6) !== '--END ' + && $info['timed_out'] !== true + && $info['eof'] !== true + ) { + $parameters['data'] .= $buff; + $buff = fgets($this->socket, 4096); + $info = stream_get_meta_data($this->socket); + } + } + } + + // store parameter in $parameters + $parameters[substr($buffer, 0, $a)] = substr($buffer, ($a + 2)); + }//end if + + $buffer = trim(fgets($this->socket, 4096)); + }//end while + + // process response + switch ($type) { + case '': + /* + Timeout or connection failure occurred. If not timed_out assume + connection failure and set timeout=true to exit while loop. + */ + $info = stream_get_meta_data($this->socket); + $timeout = ($info['timed_out'] === true) ? $allowTimeout : true; + break; + + case 'event': + $this->processEvent($parameters); + break; + + case 'response': + // nothing to process here + break; + + default: + $this->log('Unhandled response packet from Manager: '.print_r($parameters, true), self::LOG_ERROR); + break; + } + } while ($type !== 'response' && $timeout === false); + return $parameters; + }//end waitResponse() + + + /** + * Empty receive buffer + * + * @return flushed buffer + */ + public function flush() + { + $buffer = fgets($this->socket, 4096); + $info = stream_get_meta_data($this->socket); + while ($info['timed_out'] !== true && $info['eof'] !== true) { + $buffer .= fgets($this->socket, 4096); + $info = stream_get_meta_data($this->socket); + } + + return $buffer; + }//end flush() + + + /** + * Connect to Asterisk + * + * @param string|null $server Hostname to connect to. Recommend FQDN. + * @param string|null $username Username to authenticate with. + * @param string|null $secret Password for the user. + * @param boolean|string $events Toggle or filter events. + * + * @return boolean true on success + * + * @example examples/sip_show_peer.php Get information about a sip peer + */ + public function connect($server = null, $username = null, $secret = null, $events = true) + { + // use config if not specified + if ($server === null) { + $server = $this->config['asmanager']['server']; + } + + if ($username === null) { + $username = $this->config['asmanager']['username']; + } + + if ($secret === null) { + $secret = $this->config['asmanager']['secret']; + } + + // get port from server if specified + if (strpos($server, ':') !== false) { + $c = explode(':', $server); + $this->server = $c[0]; + $this->port = $c[1]; + } else { + $this->server = $server; + $this->port = $this->config['asmanager']['port']; + } + + // connect the socket + $errno = null; + $errstr = null; + // TODO: Convert this to a custom error handler to silence the error instead. + $this->socket = @fsockopen($this->server, $this->port, $errno, $errstr); + if ($this->socket === false) { + $this->log( + 'Unable to connect to manager '.$this->server.':'.$this->port.' ('.$errno.'): '.$errstr, + self::LOG_FATAL + ); + return false; + } + + // set a 2 second stream timeout + stream_set_timeout($this->socket, 2); + + // read the header + $str = fgets($this->socket); + $info = stream_get_meta_data($this->socket); + // note: else: don't $this->log($str) until someone looks to see why it mangles the logging + if ($str === false || $info['timed_out'] === true) { + // a problem. + $this->log('Asterisk Manager header not received.', self::LOG_FATAL); + return false; + } + + // login + $res = $this->sendRequest('login', ['Username' => $username, 'Secret' => $secret]); + if ($res['Response'] !== 'Success') { + $this->loggedIn = false; + $this->log('Failed to login.', self::LOG_FATAL); + $this->disconnect(); + return false; + } + + $this->loggedIn = true; + + // default state is to get all events, only send if changed + if ($events !== true && $events !== 'on') { + $this->events($events); + } + + return true; + }//end connect() + + + /** + * Disconnect + * + * @example examples/sip_show_peer.php Get information about a sip peer + * + * @return void + */ + public function disconnect() + { + if ($this->loggedIn === true) { + $this->logoff(); + } + + if (is_resource($this->socket)) { + fclose($this->socket); + } + }//end disconnect() + + + /** + * Set Absolute Timeout + * + * Hangup a channel after a certain time. + * + * @param string $channel Channel name to hangup. + * @param integer $timeout Maximum duration of the call (sec). + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+AbsoluteTimeout + */ + public function absoluteTimeout($channel, $timeout) + { + $result = $this->sendRequest('AbsoluteTimeout', ['Channel' => $channel, 'Timeout' => $timeout]); + return $result; + }//end absoluteTimeout() + + + /** + * Change monitoring filename of a channel + * + * @param string $channel The channel to record. + * @param string $file The new name of the file created in the monitor spool directory. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ChangeMonitor + */ + public function changeMonitor($channel, $file) + { + $result = $this->sendRequest('ChangeMontior', ['Channel' => $channel, 'File' => $file]); + return $result; + }//end changeMonitor() + + + /** + * Execute Command + * + * @param string $command The command to execute. + * @param string $actionId Message matching variable. + * + * @return array of parameters + * + * @example examples/sip_show_peer.php Get information about a sip peer + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Command + * @link http://www.voip-info.org/wiki-Asterisk+CLI + */ + public function command($command, $actionId = null) + { + $parameters = ['Command' => $command]; + if ($actionId !== null) { + $parameters['ActionID'] = $actionId; + } + + $result = $this->sendRequest('Command', $parameters); + return $result; + }//end command() + + + /** + * Enable/Disable sending of events to this manager + * + * @param string|boolean $eventmask Is either 'on', 'off', or 'system,call,log'. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Events + */ + public function events($eventmask) + { + if ($eventmask === true) { + $eventmask = 'on'; + } elseif ($eventmask === false) { + $eventmask = 'off'; + } + + $result = $this->sendRequest('Events', ['EventMask' => $eventmask]); + return $result; + }//end events() + + + /** + * Check Extension Status + * + * @param string $exten Extension to check state on. + * @param string $context Context for extension. + * @param string $actionId Message matching variable. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ExtensionState + */ + public function extensionState($exten, $context, $actionId = null) + { + $parameters = [ + 'Exten' => $exten, + 'Context' => $context, + ]; + if ($actionId !== null) { + $parameters['ActionID'] = $actionId; + } + + $result = $this->sendRequest('ExtensionState', $parameters); + return $result; + }//end extensionState() + + + /** + * Gets a Channel Variable + * + * @param string $channel Channel to read variable from. + * @param string $variable To retrieve. + * @param string $actionId Message matching variable. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+GetVar + * @link http://www.voip-info.org/wiki-Asterisk+variables + */ + public function getVar($channel, $variable, $actionId = null) + { + $parameters = [ + 'Channel' => $channel, + 'Variable' => $variable, + ]; + if ($actionId !== null) { + $parameters['ActionID'] = $actionId; + } + + $result = $this->sendRequest('GetVar', $parameters); + return $result; + }//end getVar() + + + /** + * Hangup Channel + * + * @param string $channel The channel name to be hungup. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Hangup + */ + public function hangup($channel) + { + $result = $this->sendRequest('Hangup', ['Channel' => $channel]); + return $result; + }//end hangup() + + + /** + * List IAX Peers + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+IAXpeers + */ + public function iaxPeers() + { + $result = $this->sendRequest('IAXPeers'); + return $result; + }//end iaxPeers() + + + /** + * List available manager commands + * + * @param string $actionId Message matching variable. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ListCommands + */ + public function listCommands($actionId = null) + { + if ($actionId !== null) { + $result = $this->sendRequest('ListCommands', ['ActionID' => $actionId]); + } else { + $result = $this->sendRequest('ListCommands'); + } + + return $result; + }//end listCommands() + + + /** + * Logoff Manager + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Logoff + */ + public function logoff() + { + $result = $this->sendRequest('Logoff'); + return $result; + }//end logoff() + + + /** + * Check Mailbox Message Count + * + * Returns number of new and old messages. + * Message: Mailbox Message Count + * Mailbox: + * NewMessages: + * OldMessages: + * + * @param string $mailbox Full mailbox ID @. + * @param string $actionId Message matching variable. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+MailboxCount + */ + public function mailboxCount($mailbox, $actionId = null) + { + $parameters = ['Mailbox' => $mailbox]; + if ($actionId !== null) { + $parameters['ActionID'] = $actionId; + } + + $results = $this->sendRequest('MailboxCount', $parameters); + return $results; + }//end mailboxCount() + + + /** + * Check Mailbox + * + * Returns number of messages. + * Message: Mailbox Status + * Mailbox: + * Waiting: + * + * @param string $mailbox Full mailbox ID @. + * @param string $actionId Message matching variable. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+MailboxStatus + */ + public function mailboxStatus($mailbox, $actionId = null) + { + $parameters = ['Mailbox' => $mailbox]; + if ($actionId !== null) { + $parameters['ActionID'] = $actionId; + } + + $result = $this->sendRequest('MailboxStatus', $parameters); + return $result; + }//end mailboxStatus() + + + /** + * Monitor a channel + * + * @param string $channel To monitor. + * @param string $file File. + * @param string $format Format. + * @param boolean $mix Mix. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Monitor + */ + public function monitor($channel, $file = null, $format = null, $mix = null) + { + $parameters = ['Channel' => $channel]; + if ($file !== null) { + $parameters['File'] = $file; + } + + if ($format !== null) { + $parameters['Format'] = $format; + } + + if ($file !== null) { + if ($mix === true) { + $parameters['Mix'] = 'true'; + } else { + $parameters['Mix'] = 'false'; + } + } + + $result = $this->sendRequest('Monitor', $parameters); + return $result; + }//end monitor() + + + /** + * Originate Call + * + * @param string $channel Channel name to call. + * @param string $exten Extension to use (requires 'Context' and 'Priority'). + * @param string $context Context to use (requires 'Exten' and 'Priority'). + * @param string $priority Priority to use (requires 'Exten' and 'Context'). + * @param string $application Application to use. + * @param string $data Data to use (requires 'Application'). + * @param integer $timeout How long to wait for call to be answered (in ms). + * @param string $callerid Caller ID to be set on the outgoing channel. + * @param string $variable Channel variable to set (VAR1=value1|VAR2=value2). + * @param string $account Account code. + * @param boolean $async True fast origination. + * @param string $actionId Message matching variable. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Originate + */ + public function originate( + $channel, + $exten = null, + $context = null, + $priority = null, + $application = null, + $data = null, + $timeout = null, + $callerid = null, + $variable = null, + $account = null, + $async = null, + $actionId = null + ) { + $parameters = ['Channel' => $channel]; + + if ($exten !== null) { + $parameters['Exten'] = $exten; + } + + if ($context !== null) { + $parameters['Context'] = $context; + } + + if ($priority !== null) { + $parameters['Priority'] = $priority; + } + + if ($application !== null) { + $parameters['Application'] = $application; + } + + if ($data !== null) { + $parameters['Data'] = $data; + } + + if ($timeout !== null) { + $parameters['Timeout'] = $timeout; + } + + if ($callerid !== null) { + $parameters['CallerID'] = $callerid; + } + + if ($variable !== null) { + $parameters['Variable'] = $variable; + } + + if ($account !== null) { + $parameters['Account'] = $account; + } + + if ($async !== null) { + if ($async === true) { + $parameters['Async'] = 'true'; + } else { + $parameters['Async'] = 'false'; + } + } + + if ($actionId !== null) { + $parameters['ActionID'] = $actionId; + } + + $result = $this->sendRequest('Originate', $parameters); + return $result; + }//end originate() + + + /** + * List parked calls + * + * @param string $actionId Message matching variable. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ParkedCalls + */ + public function parkedCalls($actionId = null) + { + if ($actionId !== null) { + $result = $this->sendRequest('ParkedCalls', ['ActionID' => $actionId]); + } else { + $result = $this->sendRequest('ParkedCalls'); + } + + return $result; + }//end parkedCalls() + + + /** + * Ping + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Ping + */ + public function ping() + { + $result = $this->sendRequest('Ping'); + return $result; + }//end ping() + + + /** + * Queue Add + * + * @param string $queue Queue. + * @param string $interface Interface. + * @param integer $penalty Penalty. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+QueueAdd + */ + public function queueAdd($queue, $interface, $penalty = 0) + { + $parameters = [ + 'Queue' => $queue, + 'Interface' => $interface, + ]; + if ($penalty !== 0) { + $parameters['Penalty'] = $penalty; + } + + $result = $this->sendRequest('QueueAdd', $parameters); + return $result; + }//end queueAdd() + + + /** + * Queue Remove + * + * @param string $queue Queue. + * @param string $interface Interface. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+QueueRemove + */ + public function queueRemove($queue, $interface) + { + $result = $this->sendRequest('QueueRemove', ['Queue' => $queue, 'Interface' => $interface]); + return $result; + }//end queueRemove() + + + /** + * Queues + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Queues + */ + public function queues() + { + $result = $this->sendRequest('Queues'); + return $result; + }//end queues() + + + /** + * Queue Status + * + * @param string $actionId Message matching variable. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+QueueStatus + */ + public function queueStatus($actionId = null) + { + if ($actionId !== null) { + $result = $this->sendRequest('QueueStatus', ['ActionID' => $actionId]); + } else { + $result = $this->sendRequest('QueueStatus'); + } + + return $result; + }//end queueStatus() + + + /** + * Redirect + * + * @param string $channel Channel. + * @param string $extrachannel Extra Channel. + * @param string $exten Exten. + * @param string $context Context. + * @param string $priority Priority. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Redirect + */ + public function redirect($channel, $extrachannel, $exten, $context, $priority) + { + $result = $this->sendRequest( + 'Redirect', + [ + 'Channel' => $channel, + 'ExtraChannel' => $extrachannel, + 'Exten' => $exten, + 'Context' => $context, + 'Priority' => $priority, + ] + ); + + return $result; + }//end redirect() + + + /** + * Set the CDR UserField + * + * @param string $userfield User field. + * @param string $channel Channel. + * @param string $append Append. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+SetCDRUserField + */ + public function setCdrUserField($userfield, $channel, $append = null) + { + $parameters = [ + 'UserField' => $userfield, + 'Channel' => $channel, + ]; + if ($append !== null) { + $parameters['Append'] = $append; + } + + $result = $this->sendRequest('SetCDRUserField', $parameters); + return $result; + }//end setCdrUserField() + + + /** + * Set Channel Variable + * + * @param string $channel Channel to set variable for. + * @param string $variable Name. + * @param string $value Value. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+SetVar + */ + public function setVar($channel, $variable, $value) + { + $result = $this->sendRequest('SetVar', ['Channel' => $channel, 'Variable' => $variable, 'Value' => $value]); + return $result; + }//end setVar() + + + /** + * Channel Status + * + * @param string $channel Channel. + * @param string $actionId Message matching variable. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+Status + */ + public function status($channel, $actionId = null) + { + $parameters = ['Channel' => $channel]; + if ($actionId !== null) { + $parameters['ActionID'] = $actionId; + } + + $result = $this->sendRequest('Status', $parameters); + return $result; + }//end status() + + + /** + * Stop monitoring a channel + * + * @param string $channel Channel. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+StopMonitor + */ + public function stopMonitor($channel) + { + $result = $this->sendRequest('StopMonitor', ['Channel' => $channel]); + return $result; + }//end stopMonitor() + + + /** + * Dial over Zap channel while offhook + * + * @param string $zapchannel Zap Channel. + * @param string $number Number. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ZapDialOffhook + */ + public function zapDialOffhook($zapchannel, $number) + { + $result = $this->sendRequest('ZapDialOffhook', ['ZapChannel' => $zapchannel, 'Number' => $number]); + return $result; + }//end zapDialOffhook() + + + /** + * Toggle Zap channel Do Not Disturb status OFF + * + * @param string $zapchannel Zap Channel. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ZapDNDoff + */ + public function zapDndOff($zapchannel) + { + $result = $this->sendRequest('ZapDNDoff', ['ZapChannel' => $zapchannel]); + return $result; + }//end zapDndOff() + + + /** + * Toggle Zap channel Do Not Disturb status ON + * + * @param string $zapchannel Zap Channel. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ZapDNDon + */ + public function zapDndOn($zapchannel) + { + $result = $this->sendRequest('ZapDNDon', ['ZapChannel' => $zapchannel]); + return $result; + }//end zapDndOn() + + + /** + * Hangup Zap Channel + * + * @param string $zapchannel Zap Channel. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ZapHangup + */ + public function zapHangup($zapchannel) + { + $result = $this->sendRequest('ZapHangup', ['ZapChannel' => $zapchannel]); + return $result; + }//end zapHangup() + + + /** + * Transfer Zap Channel + * + * @param string $zapchannel Zap Channel. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ZapTransfer + */ + public function zapTransfer($zapchannel) + { + $result = $this->sendRequest('ZapTransfer', ['ZapChannel' => $zapchannel]); + return $result; + }//end zapTransfer() + + + /** + * Zap Show Channels + * + * @param string $actionId Message matching variable. + * + * @return array of parameters + * + * @link http://www.voip-info.org/wiki-Asterisk+Manager+API+Action+ZapShowChannels + */ + public function zapShowChannels($actionId = null) + { + if ($actionId !== null) { + $result = $this->sendRequest('ZapShowChannels', ['ActionID' => $actionId]); + } else { + $result = $this->sendRequest('ZapShowChannels'); + } + + return $result; + }//end zapShowChannels() + + + /** + * Log a message + * + * @param string $message Message to log. + * @param integer $level From 1 to 4. + * + * @return void + */ + public function log($message, $level = self::LOG_INFO) + { + if ($level <= $this->logLevel) { + error_log(date('r').' - '.$message); + } + }//end log() + + + /** + * @param integer $level Log Level to use. + * + * @return void + * @throws \InvalidArgumentException Invalid Log level. + * + * @since 2015-07-25 + */ + public function setLogLevel($level) + { + if ($level < self::LOG_FATAL || $level > self::LOG_TRACE) { + throw new \InvalidArgumentException('Invalid Log Level'); + } + + $this->logLevel = $level; + }//end setLogLevel() + + + /** + * Add event handler + * + * Known Events include ( http://www.voip-info.org/wiki-asterisk+manager+events ) + * Link - Fired when two voice channels are linked together and voice data exchange commences. + * Unlink - Fired when a link between two voice channels is discontinued, for example, just before call completion. + * Newexten - + * Hangup - + * Newchannel - + * Newstate - + * Reload - Fired when the "RELOAD" console command is executed. + * Shutdown - + * ExtensionStatus - + * Rename - + * Newcallerid - + * Alarm - + * AlarmClear - + * Agentcallbacklogoff - + * Agentcallbacklogin - + * Agentlogoff - + * MeetmeJoin - + * MessageWaiting - + * join - + * leave - + * AgentCalled - + * ParkedCall - Fired after ParkedCalls + * Cdr - + * ParkedCallsComplete - + * QueueParams - + * QueueMember - + * QueueStatusEnd - + * Status - + * StatusComplete - + * ZapShowChannels - Fired after ZapShowChannels + * ZapShowChannelsComplete - + * + * @param string $event Type or * for default handler. + * @param string $callback Function. + * + * @return boolean sucess + */ + public function addEventHandler($event, $callback) + { + $event = strtolower($event); + if (isset($this->eventHandlers[$event]) === true) { + $this->log($event.' handler is already defined, not over-writing.', self::LOG_ERROR); + return false; + } + + $this->eventHandlers[$event] = $callback; + return true; + }//end addEventHandler() + + + /** + * Process event + * + * @param array $parameters Parameters. + * + * @return mixed result of event handler or false if no handler was found + */ + public function processEvent(array $parameters) + { + $ret = false; + $e = strtolower($parameters['Event']); + $this->log('Got event: '.$e, self::LOG_INFO); + + $handler = ''; + if (isset($this->eventHandlers[$e]) === true) { + $handler = $this->eventHandlers[$e]; + } elseif (isset($this->eventHandlers['*']) === true) { + $handler = $this->eventHandlers['*']; + } + + if (function_exists($handler) === true) { + $this->log('Execute handler: '.$handler, self::LOG_DEBUG); + $ret = $handler($e, $parameters, $this->server, $this->port); + } else { + $this->log('No event handler for event: '.$e, self::LOG_DEBUG); + } + + return $ret; + }//end processEvent() + + + /** + * @param string $input To split. + * + * @return array of output lines + * @since 2015-07-26 + */ + public function split($input) + { + $output = preg_split('/[\t\n]+/', $input); + return $output; + }//end split() +}//end class diff --git a/asterisk/docker-asterisk-0.9.9/test/Makefile b/asterisk/docker-asterisk-0.9.9/test/Makefile new file mode 100644 index 0000000..866c451 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/test/Makefile @@ -0,0 +1,159 @@ +# Makefile +# +# test +# + +-include *.mk + +TST_REPO ?= mlan/asterisk +TST_VER ?= latest +TST_NAME ?= test +_ver = $(if $(findstring latest,$(1)),$(2),$(2)-$(1)) + +NET_NAME ?= $(TST_NAME)-net +NET_ENV ?= --network $(NET_NAME) + +CNT_LIST ?= pbx + +PBX_NAME ?= $(TST_NAME)-pbx +PBX_DOM ?= example.com +PBX_FQDN ?= pbx.$(PBX_DOM) +PBX_CMD ?= asterisk -r +PBX_SIPP ?= 5060 +PBX_SIPS ?= 5061 +PBX_RTPP ?= 10000-10099 +PBX_SMSP ?= 8080 +EXP_ENV ?= \ +-p $(PBX_SIPP):$(PBX_SIPP)/udp \ +-p $(PBX_SIPP):$(PBX_SIPP) \ +-p $(PBX_SIPS):$(PBX_SIPS) \ +-p $(PBX_RTPP):$(PBX_RTPP)/udp \ +-p $(PBX_SMSP):80 +CAP_ENV ?= \ +--cap-add SYS_PTRACE \ +--cap-add=NET_ADMIN \ +--cap-add=NET_RAW +PBX_ENV ?= $(NET_ENV) $(EXP_ENV) $(CAP_ENV) \ +--name $(PBX_NAME) \ +--hostname $(PBX_FQDN) \ +-e SYSLOG_LEVEL=8 +PBXV_ENV ?= -v $(PBX_NAME):/srv + +TST_W8 ?= 5 + +variables: + make -pn | grep -A1 "^# makefile"| grep -v "^#\|^--" | sort | uniq + +ps: + docker ps -a + +test-all: $(addprefix test_,1 2 3 4) + + +test_%: test-up_% test-wait_% test-logs_% test-ping_% test-down_% + + +test-up_1: test-up-net + # + # + # + # test (1) run mini with defaults (is there smoke?) + # + # + docker run -d $(PBX_ENV) $(TST_REPO):$(call _ver,$(TST_VER),mini) + +test-up_2: test-up-net + # + # + # + # test (2) run base + # + # + docker run -d $(PBX_ENV) $(TST_REPO):$(call _ver,$(TST_VER),base) + +test-up_3: test-up-net + # + # + # + # test (3) run full + # + # + docker run -d $(PBX_ENV) $(TST_REPO):$(call _ver,$(TST_VER),full) + +test-up_4: test-up-net + # + # + # + # test (4) run xtra + # + # + docker run -d $(PBX_ENV) $(TST_REPO):$(call _ver,$(TST_VER),xtra) + +test-ping_%: test-version_% + # + # + # test ($*) success ☺ + # + # + # + +test-version_%: + docker exec -it $(PBX_NAME) asterisk -x "pjsip show version" | grep PJPROJECT + +test-logs_%: + docker container logs $(PBX_NAME) | grep 'docker-entrypoint.sh' || true + +test-wait_%: + sleep $(TST_W8) + +test-up-net: + docker network create $(NET_NAME) 2>/dev/null || true + +test-down: test-down_0 test-down-net test-down-vol acme-destroy + +test-down_%: + docker rm -fv $(PBX_NAME) 2>/dev/null || true + +test-down-net: + docker network rm $(NET_NAME) 2>/dev/null || true + +test-down-vol: + docker volume rm $(PBX_NAME) 2>/dev/null || true + + +$(addprefix test-,diff env htop imap logs pop3 sh sv): + ${MAKE} $(patsubst test-%,pbx-%,$@) + +$(addsuffix -sh,$(CNT_LIST)): + docker exec -it $(patsubst %-sh,$(TST_NAME)-%,$@) sh -c 'exec $$(getent passwd root | sed "s/.*://g")' + +$(addsuffix -cli,$(CNT_LIST)): + docker exec -it $(patsubst %-cli,$(TST_NAME)-%,$@) $(PBX_CMD) + +$(addsuffix -env,$(CNT_LIST)): + docker exec -it $(patsubst %-env,$(TST_NAME)-%,$@) env + +$(addsuffix -logs,$(CNT_LIST)): + docker container logs $(patsubst %-logs,$(TST_NAME)-%,$@) + +$(addsuffix -diff,$(CNT_LIST)): + docker container diff $(patsubst %-diff,$(TST_NAME)-%,$@) + +$(addsuffix -tools,$(CNT_LIST)): + docker exec -it $(patsubst %-tools,$(TST_NAME)-%,$@) \ + apk --no-cache --update add \ + nano less lsof htop openldap-clients bind-tools iputils strace util-linux \ + pulseaudio-utils alsa-utils mariadb-client + +$(addsuffix -htop,$(CNT_LIST)): + docker exec -it $(patsubst %-htop,$(TST_NAME)-%,$@) htop + +$(addsuffix -sv,$(CNT_LIST)): + docker exec -it $(patsubst %-sv,$(TST_NAME)-%,$@) sh -c 'sv status $$SVDIR/*' + + +acme-destroy: ssl-destroy + rm -f acme/* + +acme/acme.json: $(SRV_CERT) + bin/gen-acme-json.sh $(AD_USR_CN)@$(AD_DOM) $(SRV_FQDN) $(SRV_KEY) $(SRV_CERT) > $@ diff --git a/asterisk/docker-asterisk-0.9.9/test/acme/.gitignore b/asterisk/docker-asterisk-0.9.9/test/acme/.gitignore new file mode 100644 index 0000000..5e7d273 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/test/acme/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/asterisk/docker-asterisk-0.9.9/test/dkr.mk b/asterisk/docker-asterisk-0.9.9/test/dkr.mk new file mode 100644 index 0000000..f348ffc --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/test/dkr.mk @@ -0,0 +1,34 @@ +# dkr.mk +# +# Container make-functions +# + +# +# $(call dkr_srv_cnt,app) -> d03dda046e0b90c... +# +dkr_srv_cnt = $(shell docker-compose ps -q $(1) | head -n1) +# +# $(call dkr_cnt_ip,demo_app_1) -> 172.28.0.3 +# +dkr_cnt_ip = $(shell docker inspect -f \ + '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \ + $(1) | head -n1) +# +# $(call dkr_srv_ip,app) -> 172.28.0.3 +# +dkr_srv_ip = $(shell docker inspect -f \ + '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \ + $$(docker-compose ps -q $(1)) | head -n1) +# +#cnt_ip_old = $(shell docker inspect -f \ +# '{{range .NetworkSettings.Networks}}{{println .IPAddress}}{{end}}' \ +# $(1) | head -n1) + +# +# List IPs of containers +# +ip-list: + @for srv in $$(docker ps --format "{{.Names}}"); do \ + echo $$srv $$(docker inspect -f \ + '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $$srv); \ + done | column -t diff --git a/asterisk/docker-asterisk-0.9.9/test/ssl.mk b/asterisk/docker-asterisk-0.9.9/test/ssl.mk new file mode 100644 index 0000000..9d6ef1f --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/test/ssl.mk @@ -0,0 +1,125 @@ +# ssl.mk +# +# SSL and TLS make-functions +# + +SSL_O ?= example.com +SSL_KEY ?= rsa:2048 # rsa:2048 rsa:4096 +SSL_MAIL ?= +SSL_PASS ?= secret +SSL_SAN ?= +SSL_TRST ?= + +# +# Usage: OpenLDAP +# +#SSL_O = $(AD_DOM) +#target: ssl/auth.crt ssl/demo.crt + +# +# Usage: SMIME +# +#SSL_O = $(MAIL_DOMAIN) +#SSL_MAIL = auto +#SSL_PASS = $(AD_USR_PW) +##SSL_TRST = $(SSL_SMIME) +#target: ssl/$(AD_USR_CN)@$(MAIL_DOMAIN).p12 +SSL_SMIME = -setalias "Self Signed SMIME" -addtrust emailProtection \ + -addreject clientAuth -addreject serverAuth + +# +# Usage: SUbject Alternate Name SAN +# +#SSL_O = example.com +#SSL_SAN = "subjectAltName=DNS:auth,DNS:*.docker" +#target: ssl/auth.crt + + +# +# $(call ssl_subj,root,example.com,) -> -subj "/CN=root/O=example.com" +# $(call ssl_subj,root,example.com,auto) -> -subj "/CN=root/O=example.com/emailAddress=root@example.com" +# $(call ssl_subj,root,example.com,admin@my.org) -> -subj "/CN=root/O=example.com/emailAddress=admin@my.org" +# +ssl_subj = -subj "/CN=$(1)/O=$(2)$(if $(3),/emailAddress=$(if $(findstring @,$(3)),$(3),$(1)@$(2)),)" + +# +# $(call ssl_extfile,"subjectAltName=DNS:auth") -> -extfile <(printf "subjectAltName=DNS:auth") +# +ssl_extfile = $(if $(1),-extfile <(printf $(1)),) + + +.PRECIOUS: %.crt %.csr %.key +SHELL = /bin/bash + +# +# Personal information exchange file PKCS#12 +# +%.p12: %.crt + openssl pkcs12 -export -in $< -inkey $*.key -out $@ \ + -passout pass:$(SSL_PASS) + +# +# Certificate PEM +# +%.crt: %.csr ssl/ca.crt + openssl x509 -req -in $< -CA $(@D)/ca.crt -CAkey $(@D)/ca.key -out $@ \ + $(call ssl_extfile,$(SSL_SAN)) $(SSL_TRST) -CAcreateserial + +# +# Certificate signing request PEM +# +%.csr: ssl + openssl req -new -newkey $(SSL_KEY) -nodes -keyout $*.key -out $@ \ + $(call ssl_subj,$(*F),$(SSL_O),$(SSL_MAIL)) + +# +# Certificate authority certificate PEM +# +ssl/ca.crt: ssl + openssl req -x509 -new -newkey $(SSL_KEY) -nodes -keyout ssl/ca.key -out $@ \ + $(call ssl_subj,root,$(SSL_O),$(SSL_MAIL)) + +# +# SSL directory +# +ssl: + mkdir -p $@ + +# +# Remove all files in SSL directory +# +ssl-destroy: + rm -f ssl/* + +# +# Inspect all files in SSL directory +# +ssl-list: + @for file in $$(ls ssl/*); do \ + case $$file in \ + *.crt) \ + printf "\e[33;1m%s\e[0m\n" $$file; \ + openssl x509 -noout -issuer -subject -ext basicConstraints,keyUsage,extendedKeyUsage,subjectAltName -in $$file;; \ + *.csr) \ + printf "\e[33;1m%s\e[0m\n" $$file; \ + openssl req -noout -subject -in $$file;; \ + *.key) \ + printf "\e[33;1m%s\e[0m\n" $$file; \ + openssl rsa -text -noout -in $$file | head -n 1;; \ + esac \ + done + +ssl-inspect: + @for file in $$(ls ssl/*); do \ + case $$file in \ + *.crt) \ + printf "\e[33;1m%s\e[0m " $$file; \ + openssl x509 -text -noout -certopt no_sigdump,no_pubkey -in $$file;; \ + *.csr) \ + printf "\e[33;1m%s\e[0m " $$file; \ + openssl req -text -noout -reqopt no_sigdump,no_pubkey,ext_default -in $$file;; \ + *.key) \ + printf "\e[33;1m%s\e[0m " $$file; \ + openssl rsa -text -noout -in $$file | head -n 1;; \ + esac \ + done diff --git a/asterisk/docker-asterisk-0.9.9/test/ssl/.gitignore b/asterisk/docker-asterisk-0.9.9/test/ssl/.gitignore new file mode 100644 index 0000000..5e7d273 --- /dev/null +++ b/asterisk/docker-asterisk-0.9.9/test/ssl/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/docker-compose.yml b/docker-compose.yml index 64576cd..117b81d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,10 +3,12 @@ version: '2.3' services: asterisk: - image: andrius/asterisk + image: andrius/asterisk:debian-15-current deploy: mode: replicated - replicas: 3 + replicas: 1 + ports: + - "5060:5060" networks: local: aliases: @@ -22,6 +24,7 @@ services: dockerfile: Dockerfile ports: - "5060:5060/udp" + - "5060:5060/tcp" restart: always networks: local: @@ -51,3 +54,6 @@ services: networks: local: +volumes: + asterisk_conf: + asterisk_spool: diff --git a/kamailio/Dockerfile b/kamailio/Dockerfile index 54f5086..663a8dc 100644 --- a/kamailio/Dockerfile +++ b/kamailio/Dockerfile @@ -1,5 +1,5 @@ #Kamailio Test Stuff -FROM kamailio/kamailio:5.3.3-stretch +FROM kamailio/kamailio:5.5.0-stretch #Add Additional Modules @@ -7,7 +7,7 @@ FROM kamailio/kamailio:5.3.3-stretch #Copy the config file onto the Filesystem of the Docker instance COPY kamailio.cfg /etc/kamailio/ COPY dispatcher.list /etc/kamailio/ - +COPY kamctlrc /etc/kamailio/ #Print out the current IP Address info RUN ip add diff --git a/kamailio/dispatcher.list b/kamailio/dispatcher.list index 9b59832..4b0c975 100644 --- a/kamailio/dispatcher.list +++ b/kamailio/dispatcher.list @@ -1,45 +1,75 @@ { NRSETS: 1 - RECORD: { + RECORDS: { SET: { ID: 1 TARGETS: { + DEST: { + URI: sip:my-kamailio-lab_asterisk_3:5060 + FLAGS: TP + PRIORITY: 12 + ATTRS: { + BODY: rweight=50;weight=50;cc=1 + DUID: + MAXLOAD: 0 + WEIGHT: 50 + RWEIGHT: 50 + SOCKET: + SOCKNAME: + OBPROXY: + } + LATENCY: { + AVG: 0.000000 + STD: 0.000000 + EST: 0.000000 + MAX: 0 + TIMEOUT: 1 + } + } + DEST: { + URI: sip:my-kamailio-lab_asterisk_2:5060 + FLAGS: TP + PRIORITY: 12 + ATTRS: { + BODY: rweight=50;weight=50;cc=1 + DUID: + MAXLOAD: 0 + WEIGHT: 50 + RWEIGHT: 50 + SOCKET: + SOCKNAME: + OBPROXY: + } + LATENCY: { + AVG: 0.000000 + STD: 0.000000 + EST: 0.000000 + MAX: 0 + TIMEOUT: 1 + } + } DEST: { URI: sip:my-kamailio-lab_asterisk_1:5060 FLAGS: AP - PRIORITY: 0 + PRIORITY: 12 + ATTRS: { + BODY: rweight=50;weight=50;cc=1 + DUID: + MAXLOAD: 0 + WEIGHT: 50 + RWEIGHT: 50 + SOCKET: + SOCKNAME: + OBPROXY: + } LATENCY: { - AVG: 1.350000 - STD: 1.039000 - EST: 1.129000 - MAX: 3 + AVG: 1.000000 + STD: 0.000000 + EST: 1.000000 + MAX: 1 TIMEOUT: 0 } } - DEST: { - URI: sip:my-kamailio-lab_asterisk_2:5060 - FLAGS: AP - PRIORITY: 0 - LATENCY: { - AVG: 1.150000 - STD: 1.039000 - EST: 0.953000 - MAX: 3 - TIMEOUT: 0 - } - } - DEST: { - URI: sip:my-kamailio-lab_asterisk_3:5060 - FLAGS: AP - PRIORITY: 0 - LATENCY: { - AVG: 1.20000 - STD: 1.039000 - EST: 1.011000 - MAX: 3 - TIMEOUT: 0 - } - } } } } diff --git a/kamailio/dispatcher.list.001 b/kamailio/dispatcher.list.001 new file mode 100644 index 0000000..9b59832 --- /dev/null +++ b/kamailio/dispatcher.list.001 @@ -0,0 +1,46 @@ +{ + NRSETS: 1 + RECORD: { + SET: { + ID: 1 + TARGETS: { + DEST: { + URI: sip:my-kamailio-lab_asterisk_1:5060 + FLAGS: AP + PRIORITY: 0 + LATENCY: { + AVG: 1.350000 + STD: 1.039000 + EST: 1.129000 + MAX: 3 + TIMEOUT: 0 + } + } + DEST: { + URI: sip:my-kamailio-lab_asterisk_2:5060 + FLAGS: AP + PRIORITY: 0 + LATENCY: { + AVG: 1.150000 + STD: 1.039000 + EST: 0.953000 + MAX: 3 + TIMEOUT: 0 + } + } + DEST: { + URI: sip:my-kamailio-lab_asterisk_3:5060 + FLAGS: AP + PRIORITY: 0 + LATENCY: { + AVG: 1.20000 + STD: 1.039000 + EST: 1.011000 + MAX: 3 + TIMEOUT: 0 + } + } + } + } + } +} diff --git a/kamailio/kamailio.cfg b/kamailio/kamailio.cfg index 47d0fda..9eaa5fb 100644 --- a/kamailio/kamailio.cfg +++ b/kamailio/kamailio.cfg @@ -1,1124 +1,287 @@ -#!KAMAILIO -# -# Kamailio SIP Server v5.5 - default configuration script -# - web: https://www.kamailio.org -# - git: https://github.com/kamailio/kamailio -# -# Direct your questions about this file to: -# -# Refer to the Core CookBook at https://www.kamailio.org/wiki/ -# for an explanation of possible statements, functions and parameters. -# -# Note: the comments can be: -# - lines starting with #, but not the pre-processor directives, -# which start with #!, like #!define, #!ifdef, #!endif, #!else, #!trydef, -# #!subst, #!substdef, ... -# - lines starting with // -# - blocks enclosed in between /* */ -# Note: the config performs symmetric SIP signaling -# - it sends the reply to the source address of the request -# - remove the use of force_rport() for asymmetric SIP signaling -# -# Several features can be enabled using '#!define WITH_FEATURE' directives: -# -# *** To run in debug mode: -# - define WITH_DEBUG -# - debug level increased to 3, logs still sent to syslog -# - debugger module loaded with cfgtrace endabled -# -# *** To enable mysql: -# - define WITH_MYSQL -# -# *** To enable authentication execute: -# - enable mysql -# - define WITH_AUTH -# - add users using 'kamctl' or 'kamcli' -# -# *** To enable IP authentication execute: -# - enable mysql -# - enable authentication -# - define WITH_IPAUTH -# - add IP addresses with group id '1' to 'address' table -# -# *** To enable persistent user location execute: -# - enable mysql -# - define WITH_USRLOCDB -# -# *** To enable presence server execute: -# - enable mysql -# - define WITH_PRESENCE -# - if modified headers or body in config must be used by presence handling: -# - define WITH_MSGREBUILD -# -# *** To enable nat traversal execute: -# - define WITH_NAT -# - option for NAT SIP OPTIONS keepalives: WITH_NATSIPPING -# - install RTPProxy: http://www.rtpproxy.org -# - start RTPProxy: -# rtpproxy -l _your_public_ip_ -s udp:localhost:7722 -# -# *** To use RTPEngine (instead of RTPProxy) for nat traversal execute: -# - define WITH_RTPENGINE -# - install RTPEngine: https://github.com/sipwise/rtpengine -# - start RTPEngine: -# rtpengine --listen-ng=127.0.0.1:2223 ... -# -# *** To enable PSTN gateway routing execute: -# - define WITH_PSTN -# - set the value of pstn.gw_ip -# - check route[PSTN] for regexp routing condition -# -# *** To enable database aliases lookup execute: -# - enable mysql -# - define WITH_ALIASDB -# -# *** To enable speed dial lookup execute: -# - enable mysql -# - define WITH_SPEEDDIAL -# -# *** To enable multi-domain support execute: -# - enable mysql -# - define WITH_MULTIDOMAIN -# -# *** To enable TLS support execute: -# - adjust CFGDIR/tls.cfg as needed -# - define WITH_TLS -# -# *** To enable JSONRPC over HTTP(S) support execute: -# - define WITH_JSONRPC -# - adjust event_route[xhttp:request] for access policy -# -# *** 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 block 3XX redirect replies execute: -# - define WITH_BLOCK3XX -# -# *** To block 401 and 407 authentication replies execute: -# - define WITH_BLOCK401407 -# -# *** To enable VoiceMail routing execute: -# - define WITH_VOICEMAIL -# - set the value of voicemail.srv_ip -# - adjust the value of voicemail.srv_port -# -# *** To enhance accounting execute: -# - enable mysql -# - define WITH_ACCDB -# - add following columns to database - -# *** Active Modules *** -#!define WITH_MYSQL -#!define WITH_AUTH -#!define WITH_USRLOCDB -#!define WITH_MULTIDOMAIN -#!define WITH_DISPATCHER - - - -#!ifdef ACCDB_COMMENT - ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT ''; - ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT ''; - ALTER TABLE acc ADD COLUMN src_ip varchar(64) NOT NULL default ''; - ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT ''; - ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT ''; - ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT ''; - ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT ''; - ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT ''; - ALTER TABLE missed_calls ADD COLUMN src_ip varchar(64) NOT NULL default ''; - ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT ''; - ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT ''; - ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT ''; -#!endif - -####### Include Local Config If Exists ######### -import_file "kamailio-local.cfg" - -####### Defined Values ######### - -# *** Value defines - IDs used later in config -#!ifdef WITH_DEBUG -#!define DBGLEVEL 3 -#!else -#!define DBGLEVEL 2 -#!endif - -#!ifdef WITH_MYSQL -# - database URL - used to connect to database server by modules such -# as: auth_db, acc, usrloc, a.s.o. -#!define DBURL "mysql://kamailio:kamailiorw@db.local:3306/kamailio" -#!endif - -#!ifdef WITH_MULTIDOMAIN -# - the value for 'use_domain' parameters -#!define MULTIDOMAIN 1 -#!else -#!define MULTIDOMAIN 0 -#!endif - -# - flags -# FLT_ - per transaction (message) flags -#!define FLT_ACC 1 -#!define FLT_ACCMISSED 2 -#!define FLT_ACCFAILED 3 -#!define FLT_NATS 5 - -# FLB_ - per branch flags -#!define FLB_NATB 6 -#!define FLB_NATSIPPING 7 - -####### Global Parameters ######### - -/* LOG Levels: 3=DBG, 2=INFO, 1=NOTICE, 0=WARN, -1=ERR, ... */ -debug=DBGLEVEL - -/* set to 'yes' to print log messages to terminal or use '-E' cli option */ -log_stderror=no - -memdbg=5 -memlog=5 - -log_facility=LOG_LOCAL0 -log_prefix="{$mt $hdr(CSeq) $ci} " - -/* number of SIP routing processes for each UDP socket - * - value inherited by tcp_children and sctp_children when not set explicitely */ -children=8 - -/* uncomment the next line to disable TCP (default on) */ -# disable_tcp=yes - -/* number of SIP routing processes for all TCP/TLS sockets */ -# tcp_children=8 - -/* uncomment the next line to disable the auto discovery of local aliases - * based on reverse DNS on IPs (default on) */ -# auto_aliases=no - -/* add local domain aliases - it can be set many times */ -# alias="sip.mydomain.com" - -/* listen sockets - if none set, Kamailio binds to all local IP addresses - * - basic prototype (full prototype can be found in Wiki - Core Cookbook): - * listen=[proto]:[localip]:[lport] advertise [publicip]:[pport] - * - it can be set many times to add more sockets to listen to */ -# listen=udp:10.0.0.10:5060 - -/* 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=3605 - -/* upper limit for TCP connections (it includes the TLS connections) */ -tcp_max_connections=2048 - -#!ifdef WITH_JSONRPC -tcp_accept_no_cl=yes -#!endif - -#!ifdef WITH_TLS -enable_tls=yes - -/* upper limit for TLS connections */ -tls_max_connections=2048 -#!endif - -/* set it to yes to enable sctp and load sctp.so module */ -enable_sctp=no - -####### Custom Parameters ######### - -/* These parameters can be modified runtime via RPC interface - * - see the documentation of 'cfg_rpc' module. - * - * Format: group.id = value 'desc' description - * Access: $sel(cfg_get.group.id) or @cfg_get.group.id */ - -#!ifdef WITH_PSTN -/* PSTN GW Routing - * - * - pstn.gw_ip: valid IP or hostname as string value, example: - * pstn.gw_ip = "10.0.0.101" desc "My PSTN GW Address" - * - * - by default is empty to avoid misrouting */ -pstn.gw_ip = "" desc "PSTN GW Address" -pstn.gw_port = "" desc "PSTN GW Port" -#!endif - -#!ifdef WITH_VOICEMAIL -/* VoiceMail Routing on offline, busy or no answer - * - * - by default Voicemail server IP is empty to avoid misrouting */ -voicemail.srv_ip = "" desc "VoiceMail IP Address" -voicemail.srv_port = "5060" desc "VoiceMail Port" -#!endif - -####### Modules Section ######## - -/* set paths to location of modules */ -# mpath="/usr/local/lib/kamailio/modules/" - -#!ifdef WITH_MYSQL -loadmodule "db_mysql.so" -#!endif - -#!ifdef WITH_JSONRPC -loadmodule "xhttp.so" -#!endif -loadmodule "jsonrpcs.so" -loadmodule "kex.so" -loadmodule "corex.so" -loadmodule "tm.so" -loadmodule "tmx.so" -loadmodule "sl.so" -loadmodule "rr.so" -loadmodule "pv.so" -loadmodule "maxfwd.so" -loadmodule "usrloc.so" -loadmodule "registrar.so" -loadmodule "textops.so" -loadmodule "textopsx.so" -loadmodule "siputils.so" -loadmodule "xlog.so" -loadmodule "sanity.so" -loadmodule "ctl.so" -loadmodule "cfg_rpc.so" -loadmodule "acc.so" -loadmodule "counters.so" - -#!ifdef WITH_DISPATCHER -loadmodule "dispatcher.so" -#!endif - -#!ifdef WITH_AUTH -loadmodule "auth.so" -loadmodule "auth_db.so" -#!ifdef WITH_IPAUTH -loadmodule "permissions.so" -#!endif -#!endif - -#!ifdef WITH_ALIASDB -loadmodule "alias_db.so" -#!endif - -#!ifdef WITH_SPEEDDIAL -loadmodule "speeddial.so" -#!endif - -#!ifdef WITH_MULTIDOMAIN -loadmodule "domain.so" -#!endif - -#!ifdef WITH_PRESENCE -loadmodule "presence.so" -loadmodule "presence_xml.so" -#!endif - -#!ifdef WITH_NAT -loadmodule "nathelper.so" -#!ifdef WITH_RTPENGINE -loadmodule "rtpengine.so" -#!else -loadmodule "rtpproxy.so" -#!endif -#!endif - -#!ifdef WITH_TLS -loadmodule "tls.so" -#!endif - -#!ifdef WITH_ANTIFLOOD -loadmodule "htable.so" -loadmodule "pike.so" -#!endif - -#!ifdef WITH_DEBUG -loadmodule "debugger.so" -#!endif - - -#!ifdef WITH_DISPATCHER -modparam("dispatcher", "db_url", DBURL) #Use DBURL variable for database parameters -modparam("dispatcher", "ds_ping_interval", 60) #How often to ping destinations to check status -modparam("dispatcher", "ds_ping_method", "OPTIONS") #Send SIP Options ping -modparam("dispatcher", "ds_probing_threshold", 10) #How many failed pings in a row do we need before we consider it down -modparam("dispatcher", "ds_inactive_threshold", 10) #How many sucessful pings in a row do we need before considering it up -modparam("dispatcher", "ds_ping_latency_stats", 1) #Enables stats on latency -modparam("dispatcher", "ds_probing_mode", 1) #Keeps pinging gateways when state is known (to detect change in state) -modparam("dispatcher", "table_name", "dispatcher") -modparam("dispatcher", "flags", 2) -modparam("dispatcher", "xavp_dst", "_dsdst_") -modparam("dispatcher", "xavp_ctx", "_dsctx_") -modparam("dispatcher", "ds_ping_from", "sip:proxy@kamailio.org") -modparam("dispatcher", "ds_timer_mode", 1) -#!endif - -# ----------------- setting module-specific parameters --------------- - - -# ----- jsonrpcs params ----- -modparam("jsonrpcs", "pretty_format", 1) -/* set the path to RPC fifo control file */ -# modparam("jsonrpcs", "fifo_name", "/run/kamailio/kamailio_rpc.fifo") -/* set the path to RPC unix socket control file */ -# modparam("jsonrpcs", "dgram_socket", "/run/kamailio/kamailio_rpc.sock") -#!ifdef WITH_JSONRPC -modparam("jsonrpcs", "transport", 7) -#!endif - -# ----- ctl params ----- -/* set the path to RPC unix socket control file */ -# modparam("ctl", "binrpc", "unix:/run/kamailio/kamailio_ctl") - -# ----- sanity params ----- -modparam("sanity", "autodrop", 0) - -# ----- tm params ----- -# auto-discard branches from previous serial forking leg -modparam("tm", "failure_reply_mode", 3) -# default retransmission timeout: 30sec -modparam("tm", "fr_timer", 30000) -# default invite retransmission timeout after 1xx: 120sec -modparam("tm", "fr_inv_timer", 120000) - -# ----- rr params ----- -# set next param to 1 to add value to ;lr param (helps with some UAs) -modparam("rr", "enable_full_lr", 0) -# do not append from tag to the RR (no need for this script) -modparam("rr", "append_fromtag", 0) - -# ----- registrar params ----- -modparam("registrar", "method_filtering", 1) -/* uncomment the next line to disable parallel forking via location */ -# modparam("registrar", "append_branches", 0) -/* uncomment the next line not to allow more than 10 contacts per AOR */ -# modparam("registrar", "max_contacts", 10) -/* max value for expires of registrations */ -modparam("registrar", "max_expires", 3600) -/* set it to 1 to enable GRUU */ -modparam("registrar", "gruu_enabled", 0) -/* set it to 0 to disable Path handling */ -modparam("registrar", "use_path", 1) -/* save Path even if not listed in Supported header */ -modparam("registrar", "path_mode", 0) - -# ----- acc params ----- -/* what special events should be accounted ? */ -modparam("acc", "early_media", 0) -modparam("acc", "report_ack", 0) -modparam("acc", "report_cancels", 0) -/* by default ww do not adjust the direct of the sequential requests. - * if you enable this parameter, be sure the enable "append_fromtag" - * in "rr" module */ -modparam("acc", "detect_direction", 0) -/* account triggers (flags) */ -modparam("acc", "log_flag", FLT_ACC) -modparam("acc", "log_missed_flag", FLT_ACCMISSED) -modparam("acc", "log_extra", - "src_user=$fU;src_domain=$fd;src_ip=$si;" - "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") -modparam("acc", "failed_transaction_flag", FLT_ACCFAILED) -/* enhanced DB accounting */ -#!ifdef WITH_ACCDB -modparam("acc", "db_flag", FLT_ACC) -modparam("acc", "db_missed_flag", FLT_ACCMISSED) -modparam("acc", "db_url", DBURL) -modparam("acc", "db_extra", - "src_user=$fU;src_domain=$fd;src_ip=$si;" - "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") -#!endif - -# ----- usrloc params ----- -modparam("usrloc", "timer_interval", 60) -modparam("usrloc", "timer_procs", 1) -modparam("usrloc", "use_domain", MULTIDOMAIN) -/* enable DB persistency for location entries */ -#!ifdef WITH_USRLOCDB -modparam("usrloc", "db_url", DBURL) -modparam("usrloc", "db_mode", 2) -#!endif - -# ----- auth_db params ----- -#!ifdef WITH_AUTH -modparam("auth_db", "db_url", DBURL) -modparam("auth_db", "calculate_ha1", yes) -modparam("auth_db", "password_column", "password") -modparam("auth_db", "load_credentials", "") -modparam("auth_db", "use_domain", MULTIDOMAIN) - -# ----- permissions params ----- -#!ifdef WITH_IPAUTH -modparam("permissions", "db_url", DBURL) -modparam("permissions", "load_backends", 1) -#!endif - -#!endif - -# ----- alias_db params ----- -#!ifdef WITH_ALIASDB -modparam("alias_db", "db_url", DBURL) -modparam("alias_db", "use_domain", MULTIDOMAIN) -#!endif - -# ----- speeddial params ----- -#!ifdef WITH_SPEEDDIAL -modparam("speeddial", "db_url", DBURL) -modparam("speeddial", "use_domain", MULTIDOMAIN) -#!endif - -# ----- domain params ----- -#!ifdef WITH_MULTIDOMAIN -modparam("domain", "db_url", DBURL) -/* register callback to match myself condition with domains list */ -modparam("domain", "register_myself", 1) -#!endif - -#!ifdef WITH_PRESENCE -# ----- presence params ----- -modparam("presence", "db_url", DBURL) - -# ----- presence_xml params ----- -modparam("presence_xml", "db_url", DBURL) -modparam("presence_xml", "force_active", 1) -#!endif - -#!ifdef WITH_NAT -#!ifdef WITH_RTPENGINE -# ----- rtpengine params ----- -modparam("rtpengine", "rtpengine_sock", "udp:127.0.0.1:2223") -#!else -# ----- rtpproxy params ----- -modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722") -#!endif -# ----- nathelper params ----- -modparam("nathelper", "natping_interval", 30) -modparam("nathelper", "ping_nated_only", 1) -modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) -modparam("nathelper", "sipping_from", "sip:pinger@kamailio.org") - -# params needed for NAT traversal in other modules -modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)") -modparam("usrloc", "nat_bflag", FLB_NATB) -#!endif - -#!ifdef WITH_TLS -# ----- tls params ----- -modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg") -#!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;") -#!endif - -#!ifdef WITH_DEBUG -# ----- debugger params ----- -modparam("debugger", "cfgtrace", 1) -modparam("debugger", "log_level_name", "exec") -#!endif - -####### Routing Logic ######## - - -/* Main SIP request routing logic - * - processing of any incoming SIP request starts with this route - * - note: this is the same as route { ... } */ -request_route { - - # per request initial checks - route(REQINIT); - - # NAT detection - route(NATDETECT); - - # CANCEL processing - if (is_method("CANCEL")) { - if (t_check_trans()) { - route(RELAY); - } - exit; - } - - # handle retransmissions - if (!is_method("ACK")) { - if(t_precheck_trans()) { - t_check_trans(); - exit; - } - t_check_trans(); - } - - # handle requests within SIP dialogs - route(WITHINDLG); - - ### only initial requests (no To tag) - - # authentication - route(AUTH); - - # record routing for dialog forming requests (in case they are routed) - # - remove preloaded route headers - remove_hf("Route"); - if (is_method("INVITE|SUBSCRIBE")) { - record_route(); - } - - # account only INVITEs - if (is_method("INVITE")) { - setflag(FLT_ACC); # do accounting - } - - # dispatch requests to foreign domains - route(SIPOUT); - - ### requests for my local domains - - # handle presence related requests - route(PRESENCE); - - # handle registrations - route(REGISTRAR); - - if ($rU==$null) { - # request with no Username in RURI - sl_send_reply("484","Address Incomplete"); - exit; - } - - # dispatch destinations to PSTN - route(PSTN); - - # user location service - route(LOCATION); -} - -# Wrapper for relaying requests -route[RELAY] { - - # enable additional event routes for forwarded requests - # - serial forking, RTP relaying handling, a.s.o. - if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) { - if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH"); - } - if (is_method("INVITE|SUBSCRIBE|UPDATE")) { - if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY"); - } - if (is_method("INVITE")) { - if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE"); - } - - if (!t_relay()) { - sl_reply_error(); - } - exit; -} - -# Per SIP request initial checks -route[REQINIT] { - # no connect for sending replies - set_reply_no_connect(); - # enforce symmetric signaling - # - send back replies to the source address of request - force_rport(); - -#!ifdef WITH_ANTIFLOOD - # flood detection 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(src_ip!=myself) { - if($sht(ipban=>$si)!=$null) { - # ip is already blocked - xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n"); - exit; - } - if (!pike_check_req()) { - xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n"); - $sht(ipban=>$si) = 1; - exit; - } - } -#!endif - if($ua =~ "friendly|scanner|sipcli|sipvicious|VaxSIPUserAgent") { - # silent drop for scanners - uncomment next line if want to reply - # sl_send_reply("200", "OK"); - exit; - } - - if (!mf_process_maxfwd_header("10")) { - sl_send_reply("483","Too Many Hops"); - exit; - } - - if(is_method("OPTIONS") && uri==myself && $rU==$null) { - sl_send_reply("200","Keepalive"); - exit; - } - - if(!sanity_check("17895", "7")) { - xlog("Malformed SIP request from $si:$sp\n"); - exit; - } -} - -# Handle requests within SIP dialogs -route[WITHINDLG] { - if (!has_totag()) return; - - # sequential request withing a dialog should - # take the path determined by record-routing - if (loose_route()) { - route(DLGURI); - if (is_method("BYE")) { - setflag(FLT_ACC); # do accounting ... - setflag(FLT_ACCFAILED); # ... even if the transaction fails - } else if ( is_method("ACK") ) { - # ACK is forwarded statelessly - route(NATMANAGE); - } else if ( is_method("NOTIFY") ) { - # Add Record-Route for in-dialog NOTIFY as per RFC 6665. - record_route(); - } - route(RELAY); - exit; - } - - if (is_method("SUBSCRIBE") && uri == myself) { - # in-dialog subscribe requests - route(PRESENCE); - exit; - } - if ( is_method("ACK") ) { - if ( t_check_trans() ) { - # no loose-route, but stateful ACK; - # must be an ACK after a 487 - # or e.g. 404 from upstream server - route(RELAY); - exit; - } else { - # ACK without matching transaction ... ignore and discard - exit; - } - } - sl_send_reply("404","Not here"); - exit; -} - -# Handle SIP registrations -route[REGISTRAR] { - if (!is_method("REGISTER")) return; - - if(isflagset(FLT_NATS)) { - setbflag(FLB_NATB); -#!ifdef WITH_NATSIPPING - # do SIP NAT pinging - setbflag(FLB_NATSIPPING); -#!endif - } - if (!save("location")) { - sl_reply_error(); - } - exit; -} - -# User location service -route[LOCATION] { - -#!ifdef WITH_SPEEDDIAL - # search for short dialing - 2-digit extension - if($rU=~"^[0-9][0-9]$") { - if(sd_lookup("speed_dial")) { - route(SIPOUT); - } - } -#!endif - -#!ifdef WITH_ALIASDB - # search in DB-based aliases - if(alias_db_lookup("dbaliases")) { - route(SIPOUT); - } -#!endif - - $avp(oexten) = $rU; - if (!lookup("location")) { - $var(rc) = $rc; - route(TOVOICEMAIL); - t_newtran(); - switch ($var(rc)) { - case -1: - case -3: - send_reply("404", "Not Found"); - exit; - case -2: - send_reply("405", "Method Not Allowed"); - exit; - } - } - - # when routing via usrloc, log the missed calls also - if (is_method("INVITE")) { - setflag(FLT_ACCMISSED); - } - - route(RELAY); - exit; -} - -# Presence server processing -route[PRESENCE] { - if(!is_method("PUBLISH|SUBSCRIBE")) return; - - if(is_method("SUBSCRIBE") && $hdr(Event)=="message-summary") { - route(TOVOICEMAIL); - # returns here if no voicemail server is configured - sl_send_reply("404", "No voicemail service"); - exit; - } - -#!ifdef WITH_PRESENCE -#!ifdef WITH_MSGREBUILD - # apply changes in case the request headers or body were modified - msg_apply_changes(); -#!endif - if (!t_newtran()) { - sl_reply_error(); - exit; - } - - if(is_method("PUBLISH")) { - handle_publish(); - t_release(); - } else if(is_method("SUBSCRIBE")) { - handle_subscribe(); - t_release(); - } - exit; -#!endif - - # if presence enabled, this part will not be executed - if (is_method("PUBLISH") || $rU==$null) { - sl_send_reply("404", "Not here"); - exit; - } - return; -} - -# IP authorization and user authentication -route[AUTH] { -#!ifdef WITH_AUTH - -#!ifdef WITH_IPAUTH - if((!is_method("REGISTER")) && allow_source_address()) { - # source IP allowed - return; - } -#!endif - - if (is_method("REGISTER") || from_uri==myself) { - # authenticate requests - if (!auth_check("$fd", "subscriber", "1")) { - auth_challenge("$fd", "0"); - exit; - } - # user authenticated - remove auth header - if(!is_method("REGISTER|PUBLISH")) - consume_credentials(); - } - # if caller is not local subscriber, then check if it calls - # a local destination, otherwise deny, not an open relay here - if (from_uri!=myself && uri!=myself) { - sl_send_reply("403","Not relaying"); - exit; - } - -#!else - - # authentication not enabled - do not relay at all to foreign networks - if(uri!=myself) { - sl_send_reply("403","Not relaying"); - exit; - } - -#!endif - return; -} - -# Caller NAT detection -route[NATDETECT] { -#!ifdef WITH_NAT - if (nat_uac_test("19")) { - if (is_method("REGISTER")) { - fix_nated_register(); - } else { - if(is_first_hop()) { - set_contact_alias(); - } - } - setflag(FLT_NATS); - } -#!endif - return; -} - -# RTPProxy control and signaling updates for NAT traversal -route[NATMANAGE] { -#!ifdef WITH_NAT - if (is_request()) { - if(has_totag()) { - if(check_route_param("nat=yes")) { - setbflag(FLB_NATB); - } - } - } - if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) return; - -#!ifdef WITH_RTPENGINE - if(nat_uac_test("8")) { - rtpengine_manage("SIP-source-address replace-origin replace-session-connection"); - } else { - rtpengine_manage("replace-origin replace-session-connection"); - } -#!else - if(nat_uac_test("8")) { - rtpproxy_manage("co"); - } else { - rtpproxy_manage("cor"); - } -#!endif - - if (is_request()) { - if (!has_totag()) { - if(t_is_branch_route()) { - add_rr_param(";nat=yes"); - } - } - } - if (is_reply()) { - if(isbflagset(FLB_NATB)) { - if(is_first_hop()) - set_contact_alias(); - } - } - - if(isbflagset(FLB_NATB)) { - # no connect message in a dialog involving NAT traversal - if (is_request()) { - if(has_totag()) { - set_forward_no_connect(); - } - } - } -#!endif - return; -} - -# URI update for dialog requests -route[DLGURI] { -#!ifdef WITH_NAT - if(!isdsturiset()) { - handle_ruri_alias(); - } -#!endif - return; -} - -# Routing to foreign domains -route[SIPOUT] { - if (uri==myself) return; - - append_hf("P-Hint: outbound\r\n"); - route(RELAY); - exit; -} - -# PSTN GW routing -route[PSTN] { -#!ifdef WITH_PSTN - # check if PSTN GW IP is defined - if (strempty($sel(cfg_get.pstn.gw_ip))) { - xlog("SCRIPT: PSTN routing enabled but pstn.gw_ip not defined\n"); - return; - } - - # route to PSTN dialed numbers starting with '+' or '00' - # (international format) - # - update the condition to match your dialing rules for PSTN routing - if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$")) return; - - # only local users allowed to call - if(from_uri!=myself) { - sl_send_reply("403", "Not Allowed"); - exit; - } - - # normalize target number for pstn gateway - # - convert leading 00 to + - if (starts_with("$rU", "00")) { - strip(2); - prefix("+"); - } - - if (strempty($sel(cfg_get.pstn.gw_port))) { - $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip); - } else { - $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip) + ":" - + $sel(cfg_get.pstn.gw_port); - } - - route(RELAY); - exit; -#!endif - - return; -} - -# JSONRPC over HTTP(S) routing -#!ifdef WITH_JSONRPC -event_route[xhttp:request] { - set_reply_close(); - set_reply_no_connect(); - if(src_ip!=127.0.0.1) { - xhttp_reply("403", "Forbidden", "text/html", - "Not allowed from $si"); - exit; - } - if ($hu =~ "^/RPC") { - jsonrpc_dispatch(); - exit; - } - - xhttp_reply("200", "OK", "text/html", - "Wrong URL $hu"); - exit; -} -#!endif - -# Routing to voicemail server -route[TOVOICEMAIL] { -#!ifdef WITH_VOICEMAIL - if(!is_method("INVITE|SUBSCRIBE")) return; - - # check if VoiceMail server IP is defined - if (strempty($sel(cfg_get.voicemail.srv_ip))) { - xlog("SCRIPT: VoiceMail routing enabled but IP not defined\n"); - return; - } - if(is_method("INVITE")) { - if($avp(oexten)==$null) return; - - $ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip) - + ":" + $sel(cfg_get.voicemail.srv_port); - } else { - if($rU==$null) return; - - $ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip) - + ":" + $sel(cfg_get.voicemail.srv_port); - } - route(RELAY); - exit; -#!endif - - return; -} - -# Manage route dispatch -route[DISPATCH] { -#!ifdef WITH_DISPATCHER - # round robin dispatching on gateways group '1' - if(!ds_select_dst("1", "4")) { - send_reply("404", "No destination"); - exit; - } - xdbg("--- SCRIPT: going to <$ru> via <$du> (attrs: $xavp(_dsdst_=>attrs))\n"); - t_on_failure("RTF_DISPATCH"); - route(RELAY); - exit; -#!endif - return; -} - -# Try next destionations in failure route -failure_route[RTF_DISPATCH] { -#!ifdef WITH_DISPATCHER - if (t_is_canceled()) { - exit; - } - # next DST - only for 500 or local timeout - if (t_check_status("500") - or (t_branch_timeout() and !t_branch_replied())) { - if(ds_next_dst()) { - xdbg("--- SCRIPT: retrying to <$ru> via <$du> (attrs: $xavp(_dsdst_=>attrs))\n"); - t_on_failure("RTF_DISPATCH"); - route(RELAY); - exit; - } - } -#!endif - return; -} - - - - -# Manage outgoing branches -branch_route[MANAGE_BRANCH] { - xdbg("new branch [$T_branch_idx] to $ru\n"); - route(NATMANAGE); -} - -# Manage incoming replies -reply_route { - if(!sanity_check("17604", "6")) { - xlog("Malformed SIP response from $si:$sp\n"); - drop; - } -} - -# Manage incoming replies in transaction context -onreply_route[MANAGE_REPLY] { - xdbg("incoming reply\n"); - if(status=~"[12][0-9][0-9]") { - route(NATMANAGE); - } -} - -# Manage failure routing cases -failure_route[MANAGE_FAILURE] { - route(NATMANAGE); - - if (t_is_canceled()) exit; - -#!ifdef WITH_BLOCK3XX - # block call redirect based on 3xx replies. - if (t_check_status("3[0-9][0-9]")) { - t_reply("404","Not found"); - exit; - } -#!endif - -#!ifdef WITH_BLOCK401407 - # block call redirect based on 401, 407 replies. - if (t_check_status("401|407")) { - t_reply("404","Not found"); - exit; - } -#!endif - -#!ifdef WITH_VOICEMAIL - # serial forking - # - route to voicemail on busy or no answer (timeout) - if (t_check_status("486|408")) { - $du = $null; - route(TOVOICEMAIL); - exit; - } -#!endif -} +#!KAMAILIO +# +# sample config file for dispatcher module +# - load balancing of VoIP calls with round robin +# - no TPC listening +# - don't dispatch REGISTER and presence requests +# +# Kamailio SIP Server +# - web: http://www.kamailio.org +# - git: http://github.com/kamailio/ +# +# Direct your questions about this file to: sr-users@lists.kamailio.org +# +# Refer to the Core CookBook at http://www.kamailio.org/dokuwiki/doku.php +# for an explanation of possible statements, functions and parameters. +# +# Several features can be enabled using '#!define WITH_FEATURE' directives: +# +# *** To run in debug mode: +# - define WITH_DEBUG +# +#!define WITH_DEBUG + +#!ifndef DBURL +#!define DBURL "mysql://kamailio:kamailiorw@db/kamailio" +#!endif + +# - flags +# FLT_ - per transaction (message) flags +# FLB_ - per branch flags +#!define FLT_ACC 1 +#!define FLT_ACCMISSED 2 +#!define FLT_ACCFAILED 3 + +####### Global Parameters ######### + +#!ifdef WITH_DEBUG +debug=4 +log_stderror=yes +#!else +debug=2 +log_stderror=no +#!endif + +memdbg=5 +memlog=5 + +log_facility=LOG_LOCAL0 + +fork=yes +children=4 + +/* comment the next line to enable TCP */ +disable_tcp=yes + +/* uncomment the next line to disable the auto discovery of local aliases + based on revers DNS on IPs (default on) */ +auto_aliases=no + +/* add local domain aliases */ +# alias="mysipserver.com" + +port=5060 + +/* uncomment and configure the following line if you want Kamailio to + bind on a specific interface/port/proto (default bind on all available) */ +# listen=udp:127.0.0.1:5060 + +sip_warning=no + +####### Modules Section ######## + +# set module path +#mpath="/usr/local/lib/kamailio/modules/" + +loadmodule "db_mysql.so" +loadmodule "jsonrpcs.so" +loadmodule "kex.so" +loadmodule "corex.so" +loadmodule "tm.so" +loadmodule "tmx.so" +loadmodule "sl.so" +loadmodule "rr.so" +loadmodule "pv.so" +loadmodule "maxfwd.so" +loadmodule "textops.so" +loadmodule "siputils.so" +loadmodule "xlog.so" +loadmodule "sanity.so" +loadmodule "ctl.so" +loadmodule "acc.so" +loadmodule "dispatcher.so" + + +# ----------------- setting module-specific parameters --------------- + + +# ----- jsonrpcs params ----- +modparam("jsonrpcs", "pretty_format", 1) + + +# ----- 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", 0) + + +# ----- acc params ----- +modparam("acc", "log_flag", FLT_ACC) +modparam("acc", "failed_transaction_flag", FLT_ACCFAILED) +modparam("acc", "log_extra", + "src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd;src_ip=$si") + +# ----- tm params ----- +modparam("tm", "fr_timer", 2000) +modparam("tm", "fr_inv_timer", 40000) + +# ----- dispatcher params ----- +modparam("dispatcher", "db_url", DBURL) +modparam("dispatcher", "table_name", "dispatcher") +modparam("dispatcher", "flags", 2) +modparam("dispatcher", "xavp_dst", "_dsdst_") +modparam("dispatcher", "xavp_ctx", "_dsctx_") + +####### Routing Logic ######## + + +# main request routing logic + +request_route { + + # per request initial checks + route(REQINIT); + + # CANCEL processing + if (is_method("CANCEL")) { + if (t_check_trans()) { + route(RELAY); + } + exit; + } + + # handle retransmissions + if (!is_method("ACK")) { + if(t_precheck_trans()) { + t_check_trans(); + exit; + } + t_check_trans(); + } + + # handle requests within SIP dialogs + route(WITHINDLG); + + ### only initial requests (no To tag) + + # record routing for dialog forming requests (in case they are routed) + # - remove preloaded route headers + remove_hf("Route"); + if (is_method("INVITE|SUBSCRIBE")) { + record_route(); + } + + # account only INVITEs + if (is_method("INVITE")) { + setflag(FLT_ACC); # do accounting + } + + # handle presence related requests + route(PRESENCE); + + # handle registrations + route(REGISTRAR); + + if ($rU==$null) { + # request with no Username in RURI + sl_send_reply("484","Address Incomplete"); + exit; + } + + # dispatch destinations + route(DISPATCH); +} + + +route[RELAY] { + if (!t_relay()) { + sl_reply_error(); + } + exit; +} + +# Per SIP request initial checks +route[REQINIT] { + 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; + } +} + +# Handle requests within SIP dialogs +route[WITHINDLG] { + if (has_totag()) { + # sequential request withing a dialog should + # take the path determined by record-routing + if (loose_route()) { + if (is_method("BYE")) { + setflag(FLT_ACC); # do accounting ... + setflag(FLT_ACCFAILED); # ... even if the transaction fails + } + route(RELAY); + } else { + if (is_method("SUBSCRIBE") && uri == myself) { + # in-dialog subscribe requests + route(PRESENCE); + exit; + } + if ( is_method("ACK") ) { + if ( t_check_trans() ) { + # non loose-route, but stateful ACK; + # must be 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; + } +} + +# Handle SIP registrations +route[REGISTRAR] { + if(!is_method("REGISTER")) + return; + + sl_send_reply("404", "No registrar"); + exit; +} + +# Presence server route +route[PRESENCE] { + if(!is_method("PUBLISH|SUBSCRIBE")) + return; + + sl_send_reply("404", "Not here"); + exit; +} + +# Dispatch requests +route[DISPATCH] { + # round robin dispatching on gateways group '1' + if(!ds_select_dst("1", "4")) { + send_reply("404", "No destination"); + exit; + } + xdbg("--- SCRIPT: going to <$ru> via <$du> (attrs: $xavp(_dsdst_=>attrs))\n"); + t_on_failure("RTF_DISPATCH"); + route(RELAY); + exit; +} + +# Try next destionations in failure route +failure_route[RTF_DISPATCH] { + if (t_is_canceled()) { + exit; + } + # next DST - only for 500 or local timeout + if (t_check_status("500") + or (t_branch_timeout() and !t_branch_replied())) { + if(ds_next_dst()) { + xdbg("--- SCRIPT: retrying to <$ru> via <$du> (attrs: $xavp(_dsdst_=>attrs))\n"); + t_on_failure("RTF_DISPATCH"); + route(RELAY); + exit; + } + } +} diff --git a/kamailio/kamailio.cfg.001 b/kamailio/kamailio.cfg.001 new file mode 100644 index 0000000..4e9f321 --- /dev/null +++ b/kamailio/kamailio.cfg.001 @@ -0,0 +1,1128 @@ +#!KAMAILIO +# +# Kamailio SIP Server v5.5 - default configuration script +# - web: https://www.kamailio.org +# - git: https://github.com/kamailio/kamailio +# +# Direct your questions about this file to: +# +# Refer to the Core CookBook at https://www.kamailio.org/wiki/ +# for an explanation of possible statements, functions and parameters. +# +# Note: the comments can be: +# - lines starting with #, but not the pre-processor directives, +# which start with #!, like #!define, #!ifdef, #!endif, #!else, #!trydef, +# #!subst, #!substdef, ... +# - lines starting with // +# - blocks enclosed in between /* */ +# Note: the config performs symmetric SIP signaling +# - it sends the reply to the source address of the request +# - remove the use of force_rport() for asymmetric SIP signaling +# +# Several features can be enabled using '#!define WITH_FEATURE' directives: +# +# *** To run in debug mode: +# - define WITH_DEBUG +# - debug level increased to 3, logs still sent to syslog +# - debugger module loaded with cfgtrace endabled +# +# *** To enable mysql: +# - define WITH_MYSQL +# +# *** To enable authentication execute: +# - enable mysql +# - define WITH_AUTH +# - add users using 'kamctl' or 'kamcli' +# +# *** To enable IP authentication execute: +# - enable mysql +# - enable authentication +# - define WITH_IPAUTH +# - add IP addresses with group id '1' to 'address' table +# +# *** To enable persistent user location execute: +# - enable mysql +# - define WITH_USRLOCDB +# +# *** To enable presence server execute: +# - enable mysql +# - define WITH_PRESENCE +# - if modified headers or body in config must be used by presence handling: +# - define WITH_MSGREBUILD +# +# *** To enable nat traversal execute: +# - define WITH_NAT +# - option for NAT SIP OPTIONS keepalives: WITH_NATSIPPING +# - install RTPProxy: http://www.rtpproxy.org +# - start RTPProxy: +# rtpproxy -l _your_public_ip_ -s udp:localhost:7722 +# +# *** To use RTPEngine (instead of RTPProxy) for nat traversal execute: +# - define WITH_RTPENGINE +# - install RTPEngine: https://github.com/sipwise/rtpengine +# - start RTPEngine: +# rtpengine --listen-ng=127.0.0.1:2223 ... +# +# *** To enable PSTN gateway routing execute: +# - define WITH_PSTN +# - set the value of pstn.gw_ip +# - check route[PSTN] for regexp routing condition +# +# *** To enable database aliases lookup execute: +# - enable mysql +# - define WITH_ALIASDB +# +# *** To enable speed dial lookup execute: +# - enable mysql +# - define WITH_SPEEDDIAL +# +# *** To enable multi-domain support execute: +# - enable mysql +# - define WITH_MULTIDOMAIN +# +# *** To enable TLS support execute: +# - adjust CFGDIR/tls.cfg as needed +# - define WITH_TLS +# +# *** To enable JSONRPC over HTTP(S) support execute: +# - define WITH_JSONRPC +# - adjust event_route[xhttp:request] for access policy +# +# *** 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 block 3XX redirect replies execute: +# - define WITH_BLOCK3XX +# +# *** To block 401 and 407 authentication replies execute: +# - define WITH_BLOCK401407 +# +# *** To enable VoiceMail routing execute: +# - define WITH_VOICEMAIL +# - set the value of voicemail.srv_ip +# - adjust the value of voicemail.srv_port +# +# *** To enhance accounting execute: +# - enable mysql +# - define WITH_ACCDB +# - add following columns to database + +# *** Active Modules *** +#!define WITH_MYSQL +#!define WITH_AUTH +#!define WITH_USRLOCDB +#!define WITH_MULTIDOMAIN +#!define WITH_DISPATCHER + + + +#!ifdef ACCDB_COMMENT + ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT ''; + ALTER TABLE acc ADD COLUMN src_ip varchar(64) NOT NULL default ''; + ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN src_ip varchar(64) NOT NULL default ''; + ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT ''; +#!endif + +####### Include Local Config If Exists ######### +import_file "kamailio-local.cfg" + +####### Defined Values ######### + +# *** Value defines - IDs used later in config +#!ifdef WITH_DEBUG +#!define DBGLEVEL 3 +#!else +#!define DBGLEVEL 2 +#!endif + +#!ifdef WITH_MYSQL +# - database URL - used to connect to database server by modules such +# as: auth_db, acc, usrloc, a.s.o. +#!define DBURL "mysql://kamailio:kamailiorw@db.local:3306/kamailio" +#!endif + +#!ifdef WITH_MULTIDOMAIN +# - the value for 'use_domain' parameters +#!define MULTIDOMAIN 1 +#!else +#!define MULTIDOMAIN 0 +#!endif + +# - flags +# FLT_ - per transaction (message) flags +#!define FLT_ACC 1 +#!define FLT_ACCMISSED 2 +#!define FLT_ACCFAILED 3 +#!define FLT_NATS 5 + +# FLB_ - per branch flags +#!define FLB_NATB 6 +#!define FLB_NATSIPPING 7 + +####### Global Parameters ######### + +/* LOG Levels: 3=DBG, 2=INFO, 1=NOTICE, 0=WARN, -1=ERR, ... */ +debug=DBGLEVEL + +/* set to 'yes' to print log messages to terminal or use '-E' cli option */ +log_stderror=no + +memdbg=5 +memlog=5 + +log_facility=LOG_LOCAL0 +log_prefix="{$mt $hdr(CSeq) $ci} " + +/* number of SIP routing processes for each UDP socket + * - value inherited by tcp_children and sctp_children when not set explicitely */ +children=8 + +/* uncomment the next line to disable TCP (default on) */ +# disable_tcp=yes + +/* number of SIP routing processes for all TCP/TLS sockets */ +# tcp_children=8 + +/* uncomment the next line to disable the auto discovery of local aliases + * based on reverse DNS on IPs (default on) */ +# auto_aliases=no + +/* add local domain aliases - it can be set many times */ +# alias="sip.mydomain.com" + +/* listen sockets - if none set, Kamailio binds to all local IP addresses + * - basic prototype (full prototype can be found in Wiki - Core Cookbook): + * listen=[proto]:[localip]:[lport] advertise [publicip]:[pport] + * - it can be set many times to add more sockets to listen to */ +# listen=udp:10.0.0.10:5060 + +/* 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=3605 + +/* upper limit for TCP connections (it includes the TLS connections) */ +tcp_max_connections=2048 + +#!ifdef WITH_JSONRPC +tcp_accept_no_cl=yes +#!endif + +#!ifdef WITH_TLS +enable_tls=yes + +/* upper limit for TLS connections */ +tls_max_connections=2048 +#!endif + +/* set it to yes to enable sctp and load sctp.so module */ +enable_sctp=no + +####### Custom Parameters ######### + +/* These parameters can be modified runtime via RPC interface + * - see the documentation of 'cfg_rpc' module. + * + * Format: group.id = value 'desc' description + * Access: $sel(cfg_get.group.id) or @cfg_get.group.id */ + +#!ifdef WITH_PSTN +/* PSTN GW Routing + * + * - pstn.gw_ip: valid IP or hostname as string value, example: + * pstn.gw_ip = "10.0.0.101" desc "My PSTN GW Address" + * + * - by default is empty to avoid misrouting */ +pstn.gw_ip = "" desc "PSTN GW Address" +pstn.gw_port = "" desc "PSTN GW Port" +#!endif + +#!ifdef WITH_VOICEMAIL +/* VoiceMail Routing on offline, busy or no answer + * + * - by default Voicemail server IP is empty to avoid misrouting */ +voicemail.srv_ip = "" desc "VoiceMail IP Address" +voicemail.srv_port = "5060" desc "VoiceMail Port" +#!endif + +####### Modules Section ######## + +/* set paths to location of modules */ +# mpath="/usr/local/lib/kamailio/modules/" + +#!ifdef WITH_MYSQL +loadmodule "db_mysql.so" +#!endif + +#!ifdef WITH_JSONRPC +loadmodule "xhttp.so" +#!endif +loadmodule "jsonrpcs.so" +loadmodule "kex.so" +loadmodule "corex.so" +loadmodule "tm.so" +loadmodule "tmx.so" +loadmodule "sl.so" +loadmodule "rr.so" +loadmodule "pv.so" +loadmodule "maxfwd.so" +loadmodule "usrloc.so" +loadmodule "registrar.so" +loadmodule "textops.so" +loadmodule "textopsx.so" +loadmodule "siputils.so" +loadmodule "xlog.so" +loadmodule "sanity.so" +loadmodule "ctl.so" +loadmodule "cfg_rpc.so" +loadmodule "acc.so" +loadmodule "counters.so" + +#!ifdef WITH_DISPATCHER +loadmodule "dispatcher.so" +#!endif + +#!ifdef WITH_AUTH +loadmodule "auth.so" +loadmodule "auth_db.so" +#!ifdef WITH_IPAUTH +loadmodule "permissions.so" +#!endif +#!endif + +#!ifdef WITH_ALIASDB +loadmodule "alias_db.so" +#!endif + +#!ifdef WITH_SPEEDDIAL +loadmodule "speeddial.so" +#!endif + +#!ifdef WITH_MULTIDOMAIN +loadmodule "domain.so" +#!endif + +#!ifdef WITH_PRESENCE +loadmodule "presence.so" +loadmodule "presence_xml.so" +#!endif + +#!ifdef WITH_NAT +loadmodule "nathelper.so" +#!ifdef WITH_RTPENGINE +loadmodule "rtpengine.so" +#!else +loadmodule "rtpproxy.so" +#!endif +#!endif + +#!ifdef WITH_TLS +loadmodule "tls.so" +#!endif + +#!ifdef WITH_ANTIFLOOD +loadmodule "htable.so" +loadmodule "pike.so" +#!endif + +#!ifdef WITH_DEBUG +loadmodule "debugger.so" +#!endif + + +#!ifdef WITH_DISPATCHER +modparam("dispatcher", "db_url", DBURL) #Use DBURL variable for database parameters +modparam("dispatcher", "ds_ping_interval", 60) #How often to ping destinations to check status +modparam("dispatcher", "ds_ping_method", "OPTIONS") #Send SIP Options ping +modparam("dispatcher", "ds_probing_threshold", 10) #How many failed pings in a row do we need before we consider it down +modparam("dispatcher", "ds_inactive_threshold", 10) #How many sucessful pings in a row do we need before considering it up +modparam("dispatcher", "ds_ping_latency_stats", 1) #Enables stats on latency +modparam("dispatcher", "ds_probing_mode", 1) #Keeps pinging gateways when state is known (to detect change in state) +modparam("dispatcher", "table_name", "dispatcher") +modparam("dispatcher", "flags", 2) +modparam("dispatcher", "xavp_dst", "_dsdst_") +modparam("dispatcher", "xavp_ctx", "_dsctx_") +modparam("dispatcher", "ds_ping_from", "sip:proxy@kamailio.org") +modparam("dispatcher", "ds_timer_mode", 1) +#!endif + +# ----------------- setting module-specific parameters --------------- + + +# ----- jsonrpcs params ----- +modparam("jsonrpcs", "pretty_format", 1) +/* set the path to RPC fifo control file */ +# modparam("jsonrpcs", "fifo_name", "/run/kamailio/kamailio_rpc.fifo") +/* set the path to RPC unix socket control file */ +# modparam("jsonrpcs", "dgram_socket", "/run/kamailio/kamailio_rpc.sock") +#!ifdef WITH_JSONRPC +modparam("jsonrpcs", "transport", 7) +#!endif + +# ----- ctl params ----- +/* set the path to RPC unix socket control file */ +# modparam("ctl", "binrpc", "unix:/run/kamailio/kamailio_ctl") + +# ----- sanity params ----- +modparam("sanity", "autodrop", 0) + +# ----- tm params ----- +# auto-discard branches from previous serial forking leg +modparam("tm", "failure_reply_mode", 3) +# default retransmission timeout: 30sec +modparam("tm", "fr_timer", 30000) +# default invite retransmission timeout after 1xx: 120sec +modparam("tm", "fr_inv_timer", 120000) + +# ----- rr params ----- +# set next param to 1 to add value to ;lr param (helps with some UAs) +modparam("rr", "enable_full_lr", 0) +# do not append from tag to the RR (no need for this script) +modparam("rr", "append_fromtag", 0) + +# ----- registrar params ----- +modparam("registrar", "method_filtering", 1) +/* uncomment the next line to disable parallel forking via location */ +# modparam("registrar", "append_branches", 0) +/* uncomment the next line not to allow more than 10 contacts per AOR */ +# modparam("registrar", "max_contacts", 10) +/* max value for expires of registrations */ +modparam("registrar", "max_expires", 3600) +/* set it to 1 to enable GRUU */ +modparam("registrar", "gruu_enabled", 0) +/* set it to 0 to disable Path handling */ +modparam("registrar", "use_path", 1) +/* save Path even if not listed in Supported header */ +modparam("registrar", "path_mode", 0) + +# ----- acc params ----- +/* what special events should be accounted ? */ +modparam("acc", "early_media", 0) +modparam("acc", "report_ack", 0) +modparam("acc", "report_cancels", 0) +/* by default ww do not adjust the direct of the sequential requests. + * if you enable this parameter, be sure the enable "append_fromtag" + * in "rr" module */ +modparam("acc", "detect_direction", 0) +/* account triggers (flags) */ +modparam("acc", "log_flag", FLT_ACC) +modparam("acc", "log_missed_flag", FLT_ACCMISSED) +modparam("acc", "log_extra", + "src_user=$fU;src_domain=$fd;src_ip=$si;" + "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") +modparam("acc", "failed_transaction_flag", FLT_ACCFAILED) +/* enhanced DB accounting */ +#!ifdef WITH_ACCDB +modparam("acc", "db_flag", FLT_ACC) +modparam("acc", "db_missed_flag", FLT_ACCMISSED) +modparam("acc", "db_url", DBURL) +modparam("acc", "db_extra", + "src_user=$fU;src_domain=$fd;src_ip=$si;" + "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") +#!endif + +# ----- usrloc params ----- +modparam("usrloc", "timer_interval", 60) +modparam("usrloc", "timer_procs", 1) +modparam("usrloc", "use_domain", MULTIDOMAIN) +/* enable DB persistency for location entries */ +#!ifdef WITH_USRLOCDB +modparam("usrloc", "db_url", DBURL) +modparam("usrloc", "db_mode", 2) +#!endif + +# ----- auth_db params ----- +#!ifdef WITH_AUTH +modparam("auth_db", "db_url", DBURL) +modparam("auth_db", "calculate_ha1", yes) +modparam("auth_db", "password_column", "password") +modparam("auth_db", "load_credentials", "") +modparam("auth_db", "use_domain", MULTIDOMAIN) + +# ----- permissions params ----- +#!ifdef WITH_IPAUTH +modparam("permissions", "db_url", DBURL) +modparam("permissions", "load_backends", 1) +#!endif + +#!endif + +# ----- alias_db params ----- +#!ifdef WITH_ALIASDB +modparam("alias_db", "db_url", DBURL) +modparam("alias_db", "use_domain", MULTIDOMAIN) +#!endif + +# ----- speeddial params ----- +#!ifdef WITH_SPEEDDIAL +modparam("speeddial", "db_url", DBURL) +modparam("speeddial", "use_domain", MULTIDOMAIN) +#!endif + +# ----- domain params ----- +#!ifdef WITH_MULTIDOMAIN +modparam("domain", "db_url", DBURL) +/* register callback to match myself condition with domains list */ +modparam("domain", "register_myself", 1) +#!endif + +#!ifdef WITH_PRESENCE +# ----- presence params ----- +modparam("presence", "db_url", DBURL) + +# ----- presence_xml params ----- +modparam("presence_xml", "db_url", DBURL) +modparam("presence_xml", "force_active", 1) +#!endif + +#!ifdef WITH_NAT +#!ifdef WITH_RTPENGINE +# ----- rtpengine params ----- +modparam("rtpengine", "rtpengine_sock", "udp:127.0.0.1:2223") +#!else +# ----- rtpproxy params ----- +modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722") +#!endif +# ----- nathelper params ----- +modparam("nathelper", "natping_interval", 30) +modparam("nathelper", "ping_nated_only", 1) +modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) +modparam("nathelper", "sipping_from", "sip:pinger@kamailio.org") + +# params needed for NAT traversal in other modules +modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)") +modparam("usrloc", "nat_bflag", FLB_NATB) +#!endif + +#!ifdef WITH_TLS +# ----- tls params ----- +modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg") +#!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;") +#!endif + +#!ifdef WITH_DEBUG +# ----- debugger params ----- +modparam("debugger", "cfgtrace", 1) +modparam("debugger", "log_level_name", "exec") +#!endif + +####### Routing Logic ######## + + +/* Main SIP request routing logic + * - processing of any incoming SIP request starts with this route + * - note: this is the same as route { ... } */ +request_route { + + # per request initial checks + route(REQINIT); + + # NAT detection + route(NATDETECT); + + # CANCEL processing + if (is_method("CANCEL")) { + if (t_check_trans()) { + route(RELAY); + } + exit; + } + + # handle retransmissions + if (!is_method("ACK")) { + if(t_precheck_trans()) { + t_check_trans(); + exit; + } + t_check_trans(); + } + + # handle requests within SIP dialogs + route(WITHINDLG); + + ### only initial requests (no To tag) + + # authentication + route(AUTH); + + # record routing for dialog forming requests (in case they are routed) + # - remove preloaded route headers + remove_hf("Route"); + if (is_method("INVITE|SUBSCRIBE")) { + record_route(); + } + + # account only INVITEs + if (is_method("INVITE")) { + setflag(FLT_ACC); # do accounting + } + + # dispatch requests to foreign domains + route(SIPOUT); + + ### requests for my local domains + + # handle presence related requests + route(PRESENCE); + + # handle registrations + route(REGISTRAR); + + if ($rU==$null) { + # request with no Username in RURI + sl_send_reply("484","Address Incomplete"); + exit; + } + + + # dispatch destinations to PSTN + route(DISPATCH); + + # dispatch destinations to PSTN + route(PSTN); + + # user location service + route(LOCATION); +} + +# Wrapper for relaying requests +route[RELAY] { + + # enable additional event routes for forwarded requests + # - serial forking, RTP relaying handling, a.s.o. + if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) { + if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH"); + } + if (is_method("INVITE|SUBSCRIBE|UPDATE")) { + if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY"); + } + if (is_method("INVITE")) { + if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE"); + } + + if (!t_relay()) { + sl_reply_error(); + } + exit; +} + +# Per SIP request initial checks +route[REQINIT] { + # no connect for sending replies + set_reply_no_connect(); + # enforce symmetric signaling + # - send back replies to the source address of request + force_rport(); + +#!ifdef WITH_ANTIFLOOD + # flood detection 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(src_ip!=myself) { + if($sht(ipban=>$si)!=$null) { + # ip is already blocked + xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n"); + exit; + } + if (!pike_check_req()) { + xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n"); + $sht(ipban=>$si) = 1; + exit; + } + } +#!endif + if($ua =~ "friendly|scanner|sipcli|sipvicious|VaxSIPUserAgent") { + # silent drop for scanners - uncomment next line if want to reply + # sl_send_reply("200", "OK"); + exit; + } + + if (!mf_process_maxfwd_header("10")) { + sl_send_reply("483","Too Many Hops"); + exit; + } + + if(is_method("OPTIONS") && uri==myself && $rU==$null) { + sl_send_reply("200","Keepalive"); + exit; + } + + if(!sanity_check("17895", "7")) { + xlog("Malformed SIP request from $si:$sp\n"); + exit; + } +} + +# Handle requests within SIP dialogs +route[WITHINDLG] { + if (!has_totag()) return; + + # sequential request withing a dialog should + # take the path determined by record-routing + if (loose_route()) { + route(DLGURI); + if (is_method("BYE")) { + setflag(FLT_ACC); # do accounting ... + setflag(FLT_ACCFAILED); # ... even if the transaction fails + } else if ( is_method("ACK") ) { + # ACK is forwarded statelessly + route(NATMANAGE); + } else if ( is_method("NOTIFY") ) { + # Add Record-Route for in-dialog NOTIFY as per RFC 6665. + record_route(); + } + route(RELAY); + exit; + } + + if (is_method("SUBSCRIBE") && uri == myself) { + # in-dialog subscribe requests + route(PRESENCE); + exit; + } + if ( is_method("ACK") ) { + if ( t_check_trans() ) { + # no loose-route, but stateful ACK; + # must be an ACK after a 487 + # or e.g. 404 from upstream server + route(RELAY); + exit; + } else { + # ACK without matching transaction ... ignore and discard + exit; + } + } + sl_send_reply("404","Not here"); + exit; +} + +# Handle SIP registrations +route[REGISTRAR] { + if (!is_method("REGISTER")) return; + + if(isflagset(FLT_NATS)) { + setbflag(FLB_NATB); +#!ifdef WITH_NATSIPPING + # do SIP NAT pinging + setbflag(FLB_NATSIPPING); +#!endif + } + if (!save("location")) { + sl_reply_error(); + } + exit; +} + +# User location service +route[LOCATION] { + +#!ifdef WITH_SPEEDDIAL + # search for short dialing - 2-digit extension + if($rU=~"^[0-9][0-9]$") { + if(sd_lookup("speed_dial")) { + route(SIPOUT); + } + } +#!endif + +#!ifdef WITH_ALIASDB + # search in DB-based aliases + if(alias_db_lookup("dbaliases")) { + route(SIPOUT); + } +#!endif + + $avp(oexten) = $rU; + if (!lookup("location")) { + $var(rc) = $rc; + route(TOVOICEMAIL); + t_newtran(); + switch ($var(rc)) { + case -1: + case -3: + send_reply("404", "Not Found"); + exit; + case -2: + send_reply("405", "Method Not Allowed"); + exit; + } + } + + # when routing via usrloc, log the missed calls also + if (is_method("INVITE")) { + setflag(FLT_ACCMISSED); + } + + route(RELAY); + exit; +} + +# Presence server processing +route[PRESENCE] { + if(!is_method("PUBLISH|SUBSCRIBE")) return; + + if(is_method("SUBSCRIBE") && $hdr(Event)=="message-summary") { + route(TOVOICEMAIL); + # returns here if no voicemail server is configured + sl_send_reply("404", "No voicemail service"); + exit; + } + +#!ifdef WITH_PRESENCE +#!ifdef WITH_MSGREBUILD + # apply changes in case the request headers or body were modified + msg_apply_changes(); +#!endif + if (!t_newtran()) { + sl_reply_error(); + exit; + } + + if(is_method("PUBLISH")) { + handle_publish(); + t_release(); + } else if(is_method("SUBSCRIBE")) { + handle_subscribe(); + t_release(); + } + exit; +#!endif + + # if presence enabled, this part will not be executed + if (is_method("PUBLISH") || $rU==$null) { + sl_send_reply("404", "Not here"); + exit; + } + return; +} + +# IP authorization and user authentication +route[AUTH] { +#!ifdef WITH_AUTH + +#!ifdef WITH_IPAUTH + if((!is_method("REGISTER")) && allow_source_address()) { + # source IP allowed + return; + } +#!endif + + if (is_method("REGISTER") || from_uri==myself) { + # authenticate requests + if (!auth_check("$fd", "subscriber", "1")) { + auth_challenge("$fd", "0"); + exit; + } + # user authenticated - remove auth header + if(!is_method("REGISTER|PUBLISH")) + consume_credentials(); + } + # if caller is not local subscriber, then check if it calls + # a local destination, otherwise deny, not an open relay here + if (from_uri!=myself && uri!=myself) { + sl_send_reply("403","Not relaying"); + exit; + } + +#!else + + # authentication not enabled - do not relay at all to foreign networks + if(uri!=myself) { + sl_send_reply("403","Not relaying"); + exit; + } + +#!endif + return; +} + +# Caller NAT detection +route[NATDETECT] { +#!ifdef WITH_NAT + if (nat_uac_test("19")) { + if (is_method("REGISTER")) { + fix_nated_register(); + } else { + if(is_first_hop()) { + set_contact_alias(); + } + } + setflag(FLT_NATS); + } +#!endif + return; +} + +# RTPProxy control and signaling updates for NAT traversal +route[NATMANAGE] { +#!ifdef WITH_NAT + if (is_request()) { + if(has_totag()) { + if(check_route_param("nat=yes")) { + setbflag(FLB_NATB); + } + } + } + if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) return; + +#!ifdef WITH_RTPENGINE + if(nat_uac_test("8")) { + rtpengine_manage("SIP-source-address replace-origin replace-session-connection"); + } else { + rtpengine_manage("replace-origin replace-session-connection"); + } +#!else + if(nat_uac_test("8")) { + rtpproxy_manage("co"); + } else { + rtpproxy_manage("cor"); + } +#!endif + + if (is_request()) { + if (!has_totag()) { + if(t_is_branch_route()) { + add_rr_param(";nat=yes"); + } + } + } + if (is_reply()) { + if(isbflagset(FLB_NATB)) { + if(is_first_hop()) + set_contact_alias(); + } + } + + if(isbflagset(FLB_NATB)) { + # no connect message in a dialog involving NAT traversal + if (is_request()) { + if(has_totag()) { + set_forward_no_connect(); + } + } + } +#!endif + return; +} + +# URI update for dialog requests +route[DLGURI] { +#!ifdef WITH_NAT + if(!isdsturiset()) { + handle_ruri_alias(); + } +#!endif + return; +} + +# Routing to foreign domains +route[SIPOUT] { + if (uri==myself) return; + + append_hf("P-Hint: outbound\r\n"); + route(RELAY); + exit; +} + +# PSTN GW routing +route[PSTN] { +#!ifdef WITH_PSTN + # check if PSTN GW IP is defined + if (strempty($sel(cfg_get.pstn.gw_ip))) { + xlog("SCRIPT: PSTN routing enabled but pstn.gw_ip not defined\n"); + return; + } + + # route to PSTN dialed numbers starting with '+' or '00' + # (international format) + # - update the condition to match your dialing rules for PSTN routing + if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$")) return; + + # only local users allowed to call + if(from_uri!=myself) { + sl_send_reply("403", "Not Allowed"); + exit; + } + + # normalize target number for pstn gateway + # - convert leading 00 to + + if (starts_with("$rU", "00")) { + strip(2); + prefix("+"); + } + + if (strempty($sel(cfg_get.pstn.gw_port))) { + $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip); + } else { + $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip) + ":" + + $sel(cfg_get.pstn.gw_port); + } + + route(RELAY); + exit; +#!endif + + return; +} + +# JSONRPC over HTTP(S) routing +#!ifdef WITH_JSONRPC +event_route[xhttp:request] { + set_reply_close(); + set_reply_no_connect(); + if(src_ip!=127.0.0.1) { + xhttp_reply("403", "Forbidden", "text/html", + "Not allowed from $si"); + exit; + } + if ($hu =~ "^/RPC") { + jsonrpc_dispatch(); + exit; + } + + xhttp_reply("200", "OK", "text/html", + "Wrong URL $hu"); + exit; +} +#!endif + +# Routing to voicemail server +route[TOVOICEMAIL] { +#!ifdef WITH_VOICEMAIL + if(!is_method("INVITE|SUBSCRIBE")) return; + + # check if VoiceMail server IP is defined + if (strempty($sel(cfg_get.voicemail.srv_ip))) { + xlog("SCRIPT: VoiceMail routing enabled but IP not defined\n"); + return; + } + if(is_method("INVITE")) { + if($avp(oexten)==$null) return; + + $ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip) + + ":" + $sel(cfg_get.voicemail.srv_port); + } else { + if($rU==$null) return; + + $ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip) + + ":" + $sel(cfg_get.voicemail.srv_port); + } + route(RELAY); + exit; +#!endif + + return; +} + +# Manage route dispatch +route[DISPATCH] { +#!ifdef WITH_DISPATCHER + # round robin dispatching on gateways group '1' + if(!ds_select_dst("1", "4")) { + send_reply("404", "No destination"); + exit; + } + xdbg("--- SCRIPT: going to <$ru> via <$du> (attrs: $xavp(_dsdst_=>attrs))\n"); + t_on_failure("RTF_DISPATCH"); + route(RELAY); + exit; +#!endif + return; +} + +# Try next destionations in failure route +failure_route[RTF_DISPATCH] { +#!ifdef WITH_DISPATCHER + if (t_is_canceled()) { + exit; + } + # next DST - only for 500 or local timeout + if (t_check_status("500") + or (t_branch_timeout() and !t_branch_replied())) { + if(ds_next_dst()) { + xdbg("--- SCRIPT: retrying to <$ru> via <$du> (attrs: $xavp(_dsdst_=>attrs))\n"); + t_on_failure("RTF_DISPATCH"); + route(RELAY); + exit; + } + } +#!endif + return; +} + + + + +# Manage outgoing branches +branch_route[MANAGE_BRANCH] { + xdbg("new branch [$T_branch_idx] to $ru\n"); + route(NATMANAGE); +} + +# Manage incoming replies +reply_route { + if(!sanity_check("17604", "6")) { + xlog("Malformed SIP response from $si:$sp\n"); + drop; + } +} + +# Manage incoming replies in transaction context +onreply_route[MANAGE_REPLY] { + xdbg("incoming reply\n"); + if(status=~"[12][0-9][0-9]") { + route(NATMANAGE); + } +} + +# Manage failure routing cases +failure_route[MANAGE_FAILURE] { + route(NATMANAGE); + + if (t_is_canceled()) exit; + +#!ifdef WITH_BLOCK3XX + # block call redirect based on 3xx replies. + if (t_check_status("3[0-9][0-9]")) { + t_reply("404","Not found"); + exit; + } +#!endif + +#!ifdef WITH_BLOCK401407 + # block call redirect based on 401, 407 replies. + if (t_check_status("401|407")) { + t_reply("404","Not found"); + exit; + } +#!endif + +#!ifdef WITH_VOICEMAIL + # serial forking + # - route to voicemail on busy or no answer (timeout) + if (t_check_status("486|408")) { + $du = $null; + route(TOVOICEMAIL); + exit; + } +#!endif +} diff --git a/kamailio/kamailio.cfg.002 b/kamailio/kamailio.cfg.002 new file mode 100644 index 0000000..00b37ad --- /dev/null +++ b/kamailio/kamailio.cfg.002 @@ -0,0 +1,1124 @@ +#!KAMAILIO +# +# Kamailio SIP Server v5.5 - default configuration script +# - web: https://www.kamailio.org +# - git: https://github.com/kamailio/kamailio +# +# Direct your questions about this file to: +# +# Refer to the Core CookBook at https://www.kamailio.org/wiki/ +# for an explanation of possible statements, functions and parameters. +# +# Note: the comments can be: +# - lines starting with #, but not the pre-processor directives, +# which start with #!, like #!define, #!ifdef, #!endif, #!else, #!trydef, +# #!subst, #!substdef, ... +# - lines starting with // +# - blocks enclosed in between /* */ +# Note: the config performs symmetric SIP signaling +# - it sends the reply to the source address of the request +# - remove the use of force_rport() for asymmetric SIP signaling +# +# Several features can be enabled using '#!define WITH_FEATURE' directives: +# +# *** To run in debug mode: +# - define WITH_DEBUG +# - debug level increased to 3, logs still sent to syslog +# - debugger module loaded with cfgtrace endabled +# +# *** To enable mysql: +# - define WITH_MYSQL +# +# *** To enable authentication execute: +# - enable mysql +# - define WITH_AUTH +# - add users using 'kamctl' or 'kamcli' +# +# *** To enable IP authentication execute: +# - enable mysql +# - enable authentication +# - define WITH_IPAUTH +# - add IP addresses with group id '1' to 'address' table +# +# *** To enable persistent user location execute: +# - enable mysql +# - define WITH_USRLOCDB +# +# *** To enable presence server execute: +# - enable mysql +# - define WITH_PRESENCE +# - if modified headers or body in config must be used by presence handling: +# - define WITH_MSGREBUILD +# +# *** To enable nat traversal execute: +# - define WITH_NAT +# - option for NAT SIP OPTIONS keepalives: WITH_NATSIPPING +# - install RTPProxy: http://www.rtpproxy.org +# - start RTPProxy: +# rtpproxy -l _your_public_ip_ -s udp:localhost:7722 +# +# *** To use RTPEngine (instead of RTPProxy) for nat traversal execute: +# - define WITH_RTPENGINE +# - install RTPEngine: https://github.com/sipwise/rtpengine +# - start RTPEngine: +# rtpengine --listen-ng=127.0.0.1:2223 ... +# +# *** To enable PSTN gateway routing execute: +# - define WITH_PSTN +# - set the value of pstn.gw_ip +# - check route[PSTN] for regexp routing condition +# +# *** To enable database aliases lookup execute: +# - enable mysql +# - define WITH_ALIASDB +# +# *** To enable speed dial lookup execute: +# - enable mysql +# - define WITH_SPEEDDIAL +# +# *** To enable multi-domain support execute: +# - enable mysql +# - define WITH_MULTIDOMAIN +# +# *** To enable TLS support execute: +# - adjust CFGDIR/tls.cfg as needed +# - define WITH_TLS +# +# *** To enable JSONRPC over HTTP(S) support execute: +# - define WITH_JSONRPC +# - adjust event_route[xhttp:request] for access policy +# +# *** 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 block 3XX redirect replies execute: +# - define WITH_BLOCK3XX +# +# *** To block 401 and 407 authentication replies execute: +# - define WITH_BLOCK401407 +# +# *** To enable VoiceMail routing execute: +# - define WITH_VOICEMAIL +# - set the value of voicemail.srv_ip +# - adjust the value of voicemail.srv_port +# +# *** To enhance accounting execute: +# - enable mysql +# - define WITH_ACCDB +# - add following columns to database +#!ifdef ACCDB_COMMENT + ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT ''; + ALTER TABLE acc ADD COLUMN src_ip varchar(64) NOT NULL default ''; + ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN src_ip varchar(64) NOT NULL default ''; + ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT ''; +#!endif + +####### Include Local Config If Exists ######### +import_file "kamailio-local.cfg" + +####### Defined Values ######### +#!define WITH_MYSQL +#!define WITH_AUTH +#!define WITH_USRLOCDB +#!define WITH_MULTIDOMAIN +#!define WITH_DISPATCHER +#!define WITH_DEBUG + + + + + + + + + + + +# *** Value defines - IDs used later in config +#!ifdef WITH_DEBUG +#!define DBGLEVEL 3 +#!else +#!define DBGLEVEL 2 +#!endif + +#!ifdef WITH_MYSQL +# - database URL - used to connect to database server by modules such +# as: auth_db, acc, usrloc, a.s.o. +#!trydef DBURL "mysql://kamailio:kamailiorw@db.local:3306/kamailio" +#!endif + +#!ifdef WITH_MULTIDOMAIN +# - the value for 'use_domain' parameters +#!define MULTIDOMAIN 1 +#!else +#!define MULTIDOMAIN 0 +#!endif + +# - flags +# FLT_ - per transaction (message) flags +#!define FLT_ACC 1 +#!define FLT_ACCMISSED 2 +#!define FLT_ACCFAILED 3 +#!define FLT_NATS 5 + +# FLB_ - per branch flags +#!define FLB_NATB 6 +#!define FLB_NATSIPPING 7 + +####### Global Parameters ######### + +/* LOG Levels: 3=DBG, 2=INFO, 1=NOTICE, 0=WARN, -1=ERR, ... */ +debug=DBGLEVEL + +/* set to 'yes' to print log messages to terminal or use '-E' cli option */ +log_stderror=no + +memdbg=5 +memlog=5 + +log_facility=LOG_LOCAL0 +log_prefix="{$mt $hdr(CSeq) $ci} " + +/* number of SIP routing processes for each UDP socket + * - value inherited by tcp_children and sctp_children when not set explicitely */ +children=8 + +/* uncomment the next line to disable TCP (default on) */ +# disable_tcp=yes + +/* number of SIP routing processes for all TCP/TLS sockets */ +# tcp_children=8 + +/* uncomment the next line to disable the auto discovery of local aliases + * based on reverse DNS on IPs (default on) */ +# auto_aliases=no + +/* add local domain aliases - it can be set many times */ +# alias="sip.mydomain.com" + +/* listen sockets - if none set, Kamailio binds to all local IP addresses + * - basic prototype (full prototype can be found in Wiki - Core Cookbook): + * listen=[proto]:[localip]:[lport] advertise [publicip]:[pport] + * - it can be set many times to add more sockets to listen to */ +# listen=udp:10.0.0.10:5060 + +/* 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=3605 + +/* upper limit for TCP connections (it includes the TLS connections) */ +tcp_max_connections=2048 + +#!ifdef WITH_JSONRPC +tcp_accept_no_cl=yes +#!endif + +#!ifdef WITH_TLS +enable_tls=yes + +/* upper limit for TLS connections */ +tls_max_connections=2048 +#!endif + +/* set it to yes to enable sctp and load sctp.so module */ +enable_sctp=no + +####### Custom Parameters ######### + +/* These parameters can be modified runtime via RPC interface + * - see the documentation of 'cfg_rpc' module. + * + * Format: group.id = value 'desc' description + * Access: $sel(cfg_get.group.id) or @cfg_get.group.id */ + +#!ifdef WITH_PSTN +/* PSTN GW Routing + * + * - pstn.gw_ip: valid IP or hostname as string value, example: + * pstn.gw_ip = "10.0.0.101" desc "My PSTN GW Address" + * + * - by default is empty to avoid misrouting */ +pstn.gw_ip = "" desc "PSTN GW Address" +pstn.gw_port = "" desc "PSTN GW Port" +#!endif + +#!ifdef WITH_VOICEMAIL +/* VoiceMail Routing on offline, busy or no answer + * + * - by default Voicemail server IP is empty to avoid misrouting */ +voicemail.srv_ip = "" desc "VoiceMail IP Address" +voicemail.srv_port = "5060" desc "VoiceMail Port" +#!endif + +####### Modules Section ######## + +/* set paths to location of modules */ +# mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules/" + +#!ifdef WITH_MYSQL +loadmodule "db_mysql.so" +#!endif + +#!ifdef WITH_JSONRPC +loadmodule "xhttp.so" +#!endif +loadmodule "jsonrpcs.so" +loadmodule "kex.so" +loadmodule "corex.so" +loadmodule "tm.so" +loadmodule "tmx.so" +loadmodule "sl.so" +loadmodule "rr.so" +loadmodule "pv.so" +loadmodule "maxfwd.so" +loadmodule "usrloc.so" +loadmodule "registrar.so" +loadmodule "textops.so" +loadmodule "textopsx.so" +loadmodule "siputils.so" +loadmodule "xlog.so" +loadmodule "sanity.so" +loadmodule "ctl.so" +loadmodule "cfg_rpc.so" +loadmodule "acc.so" +loadmodule "counters.so" + +#!ifdef WITH_AUTH +loadmodule "auth.so" +loadmodule "auth_db.so" +#!ifdef WITH_IPAUTH +loadmodule "permissions.so" +#!endif +#!endif + +#!ifdef WITH_ALIASDB +loadmodule "alias_db.so" +#!endif + +#!ifdef WITH_SPEEDDIAL +loadmodule "speeddial.so" +#!endif + +#!ifdef WITH_MULTIDOMAIN +loadmodule "domain.so" +#!endif + +#!ifdef WITH_PRESENCE +loadmodule "presence.so" +loadmodule "presence_xml.so" +#!endif + +#!ifdef WITH_NAT +loadmodule "nathelper.so" +#!ifdef WITH_RTPENGINE +loadmodule "rtpengine.so" +#!else +loadmodule "rtpproxy.so" +#!endif +#!endif + +#!ifdef WITH_TLS +loadmodule "tls.so" +#!endif + +#!ifdef WITH_ANTIFLOOD +loadmodule "htable.so" +loadmodule "pike.so" +#!endif + +#!ifdef WITH_DEBUG +loadmodule "debugger.so" +#!endif + +#!ifdef WITH_DISPATCHER +loadmodule "dispatcher.so" +#!endif + +# ----------------- setting module-specific parameters --------------- + +# ----- dispatcher params ----- +#!ifdef WITH_DISPATCHER +modparam("dispatcher", "db_url", DBURL) #Use DBURL variable for database parameters +modparam("dispatcher", "ds_ping_interval", 60) #How often to ping destinations to check status +modparam("dispatcher", "ds_ping_method", "OPTIONS") #Send SIP Options ping +modparam("dispatcher", "ds_probing_threshold", 10) #How many failed pings in a row do we need before we consider it down +modparam("dispatcher", "ds_inactive_threshold", 10) #How many sucessful pings in a row do we need before considering it up +modparam("dispatcher", "ds_ping_latency_stats", 1) #Enables stats on latency +modparam("dispatcher", "ds_probing_mode", 1) #Keeps pinging gateways when state is known (to detect change in state) +modparam("dispatcher", "table_name", "dispatcher") +modparam("dispatcher", "flags", 2) +modparam("dispatcher", "xavp_dst", "_dsdst_") +modparam("dispatcher", "xavp_ctx", "_dsctx_") +modparam("dispatcher", "ds_ping_from", "sip:proxy@kamailio.org") +modparam("dispatcher", "ds_timer_mode", 1) +#!endif + + + +# ----- jsonrpcs params ----- +modparam("jsonrpcs", "pretty_format", 1) +/* set the path to RPC fifo control file */ +# modparam("jsonrpcs", "fifo_name", "/run/kamailio/kamailio_rpc.fifo") +/* set the path to RPC unix socket control file */ +# modparam("jsonrpcs", "dgram_socket", "/run/kamailio/kamailio_rpc.sock") +#!ifdef WITH_JSONRPC +modparam("jsonrpcs", "transport", 7) +#!endif + +# ----- ctl params ----- +/* set the path to RPC unix socket control file */ +# modparam("ctl", "binrpc", "unix:/run/kamailio/kamailio_ctl") + +# ----- sanity params ----- +modparam("sanity", "autodrop", 0) + +# ----- tm params ----- +# auto-discard branches from previous serial forking leg +modparam("tm", "failure_reply_mode", 3) +# default retransmission timeout: 30sec +modparam("tm", "fr_timer", 30000) +# default invite retransmission timeout after 1xx: 120sec +modparam("tm", "fr_inv_timer", 120000) + +# ----- rr params ----- +# set next param to 1 to add value to ;lr param (helps with some UAs) +modparam("rr", "enable_full_lr", 0) +# do not append from tag to the RR (no need for this script) +modparam("rr", "append_fromtag", 0) + +# ----- registrar params ----- +modparam("registrar", "method_filtering", 1) +/* uncomment the next line to disable parallel forking via location */ +# modparam("registrar", "append_branches", 0) +/* uncomment the next line not to allow more than 10 contacts per AOR */ +# modparam("registrar", "max_contacts", 10) +/* max value for expires of registrations */ +modparam("registrar", "max_expires", 3600) +/* set it to 1 to enable GRUU */ +modparam("registrar", "gruu_enabled", 0) +/* set it to 0 to disable Path handling */ +modparam("registrar", "use_path", 1) +/* save Path even if not listed in Supported header */ +modparam("registrar", "path_mode", 0) + +# ----- acc params ----- +/* what special events should be accounted ? */ +modparam("acc", "early_media", 0) +modparam("acc", "report_ack", 0) +modparam("acc", "report_cancels", 0) +/* by default ww do not adjust the direct of the sequential requests. + * if you enable this parameter, be sure the enable "append_fromtag" + * in "rr" module */ +modparam("acc", "detect_direction", 0) +/* account triggers (flags) */ +modparam("acc", "log_flag", FLT_ACC) +modparam("acc", "log_missed_flag", FLT_ACCMISSED) +modparam("acc", "log_extra", + "src_user=$fU;src_domain=$fd;src_ip=$si;" + "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") +modparam("acc", "failed_transaction_flag", FLT_ACCFAILED) +/* enhanced DB accounting */ +#!ifdef WITH_ACCDB +modparam("acc", "db_flag", FLT_ACC) +modparam("acc", "db_missed_flag", FLT_ACCMISSED) +modparam("acc", "db_url", DBURL) +modparam("acc", "db_extra", + "src_user=$fU;src_domain=$fd;src_ip=$si;" + "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") +#!endif + +# ----- usrloc params ----- +modparam("usrloc", "timer_interval", 60) +modparam("usrloc", "timer_procs", 1) +modparam("usrloc", "use_domain", MULTIDOMAIN) +/* enable DB persistency for location entries */ +#!ifdef WITH_USRLOCDB +modparam("usrloc", "db_url", DBURL) +modparam("usrloc", "db_mode", 2) +#!endif + +# ----- auth_db params ----- +#!ifdef WITH_AUTH +modparam("auth_db", "db_url", DBURL) +modparam("auth_db", "calculate_ha1", yes) +modparam("auth_db", "password_column", "password") +modparam("auth_db", "load_credentials", "") +modparam("auth_db", "use_domain", MULTIDOMAIN) + +# ----- permissions params ----- +#!ifdef WITH_IPAUTH +modparam("permissions", "db_url", DBURL) +modparam("permissions", "load_backends", 1) +#!endif + +#!endif + +# ----- alias_db params ----- +#!ifdef WITH_ALIASDB +modparam("alias_db", "db_url", DBURL) +modparam("alias_db", "use_domain", MULTIDOMAIN) +#!endif + +# ----- speeddial params ----- +#!ifdef WITH_SPEEDDIAL +modparam("speeddial", "db_url", DBURL) +modparam("speeddial", "use_domain", MULTIDOMAIN) +#!endif + +# ----- domain params ----- +#!ifdef WITH_MULTIDOMAIN +modparam("domain", "db_url", DBURL) +/* register callback to match myself condition with domains list */ +modparam("domain", "register_myself", 1) +#!endif + +#!ifdef WITH_PRESENCE +# ----- presence params ----- +modparam("presence", "db_url", DBURL) + +# ----- presence_xml params ----- +modparam("presence_xml", "db_url", DBURL) +modparam("presence_xml", "force_active", 1) +#!endif + +#!ifdef WITH_NAT +#!ifdef WITH_RTPENGINE +# ----- rtpengine params ----- +modparam("rtpengine", "rtpengine_sock", "udp:127.0.0.1:2223") +#!else +# ----- rtpproxy params ----- +modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722") +#!endif +# ----- nathelper params ----- +modparam("nathelper", "natping_interval", 30) +modparam("nathelper", "ping_nated_only", 1) +modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) +modparam("nathelper", "sipping_from", "sip:pinger@kamailio.org") + +# params needed for NAT traversal in other modules +modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)") +modparam("usrloc", "nat_bflag", FLB_NATB) +#!endif + +#!ifdef WITH_TLS +# ----- tls params ----- +modparam("tls", "config", "/etc/kamailio/tls.cfg") +#!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;") +#!endif + +#!ifdef WITH_DEBUG +# ----- debugger params ----- +modparam("debugger", "cfgtrace", 1) +modparam("debugger", "log_level_name", "exec") +#!endif + +####### Routing Logic ######## + + +/* Main SIP request routing logic + * - processing of any incoming SIP request starts with this route + * - note: this is the same as route { ... } */ +request_route { + + # per request initial checks + route(REQINIT); + + # NAT detection + route(NATDETECT); + + # CANCEL processing + if (is_method("CANCEL")) { + if (t_check_trans()) { + route(RELAY); + } + exit; + } + + # handle retransmissions + if (!is_method("ACK")) { + if(t_precheck_trans()) { + t_check_trans(); + exit; + } + t_check_trans(); + } + + # handle requests within SIP dialogs + route(WITHINDLG); + + ### only initial requests (no To tag) + + # authentication + route(AUTH); + + # record routing for dialog forming requests (in case they are routed) + # - remove preloaded route headers + remove_hf("Route"); + if (is_method("INVITE|SUBSCRIBE")) { + record_route(); + } + + # account only INVITEs + if (is_method("INVITE")) { + setflag(FLT_ACC); # do accounting + } + + # dispatch requests to foreign domains + route(SIPOUT); + + ### requests for my local domains + + # handle presence related requests + route(PRESENCE); + + # handle registrations + route(REGISTRAR); + + if ($rU==$null) { + # request with no Username in RURI + sl_send_reply("484","Address Incomplete"); + exit; + } + + route(DISPATCH) + + # dispatch destinations to PSTN + route(PSTN); + + # user location service + route(LOCATION); +} + +# Wrapper for relaying requests +route[RELAY] { + + # enable additional event routes for forwarded requests + # - serial forking, RTP relaying handling, a.s.o. + if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) { + if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH"); + } + if (is_method("INVITE|SUBSCRIBE|UPDATE")) { + if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY"); + } + if (is_method("INVITE")) { + if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE"); + } + + if (!t_relay()) { + sl_reply_error(); + } + exit; +} + +# Per SIP request initial checks +route[REQINIT] { + # no connect for sending replies + set_reply_no_connect(); + # enforce symmetric signaling + # - send back replies to the source address of request + force_rport(); + +#!ifdef WITH_ANTIFLOOD + # flood detection 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(src_ip!=myself) { + if($sht(ipban=>$si)!=$null) { + # ip is already blocked + xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n"); + exit; + } + if (!pike_check_req()) { + xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n"); + $sht(ipban=>$si) = 1; + exit; + } + } +#!endif + if($ua =~ "friendly|scanner|sipcli|sipvicious|VaxSIPUserAgent") { + # silent drop for scanners - uncomment next line if want to reply + # sl_send_reply("200", "OK"); + exit; + } + + if (!mf_process_maxfwd_header("10")) { + sl_send_reply("483","Too Many Hops"); + exit; + } + + if(is_method("OPTIONS") && uri==myself && $rU==$null) { + sl_send_reply("200","Keepalive"); + exit; + } + + if(!sanity_check("17895", "7")) { + xlog("Malformed SIP request from $si:$sp\n"); + exit; + } +} + +# Handle requests within SIP dialogs +route[WITHINDLG] { + if (!has_totag()) return; + + # sequential request withing a dialog should + # take the path determined by record-routing + if (loose_route()) { + route(DLGURI); + if (is_method("BYE")) { + setflag(FLT_ACC); # do accounting ... + setflag(FLT_ACCFAILED); # ... even if the transaction fails + } else if ( is_method("ACK") ) { + # ACK is forwarded statelessly + route(NATMANAGE); + } else if ( is_method("NOTIFY") ) { + # Add Record-Route for in-dialog NOTIFY as per RFC 6665. + record_route(); + } + route(RELAY); + exit; + } + + if (is_method("SUBSCRIBE") && uri == myself) { + # in-dialog subscribe requests + route(PRESENCE); + exit; + } + if ( is_method("ACK") ) { + if ( t_check_trans() ) { + # no loose-route, but stateful ACK; + # must be an ACK after a 487 + # or e.g. 404 from upstream server + route(RELAY); + exit; + } else { + # ACK without matching transaction ... ignore and discard + exit; + } + } + sl_send_reply("404","Not here"); + exit; +} + +# Handle SIP registrations +route[REGISTRAR] { + if (!is_method("REGISTER")) return; + + if(isflagset(FLT_NATS)) { + setbflag(FLB_NATB); +#!ifdef WITH_NATSIPPING + # do SIP NAT pinging + setbflag(FLB_NATSIPPING); +#!endif + } + if (!save("location")) { + sl_reply_error(); + } + exit; +} + +# User location service +route[LOCATION] { + +#!ifdef WITH_SPEEDDIAL + # search for short dialing - 2-digit extension + if($rU=~"^[0-9][0-9]$") { + if(sd_lookup("speed_dial")) { + route(SIPOUT); + } + } +#!endif + +#!ifdef WITH_ALIASDB + # search in DB-based aliases + if(alias_db_lookup("dbaliases")) { + route(SIPOUT); + } +#!endif + + $avp(oexten) = $rU; + if (!lookup("location")) { + $var(rc) = $rc; + route(TOVOICEMAIL); + t_newtran(); + switch ($var(rc)) { + case -1: + case -3: + send_reply("404", "Not Found"); + exit; + case -2: + send_reply("405", "Method Not Allowed"); + exit; + } + } + + # when routing via usrloc, log the missed calls also + if (is_method("INVITE")) { + setflag(FLT_ACCMISSED); + } + + route(RELAY); + exit; +} + +# Presence server processing +route[PRESENCE] { + if(!is_method("PUBLISH|SUBSCRIBE")) return; + + if(is_method("SUBSCRIBE") && $hdr(Event)=="message-summary") { + route(TOVOICEMAIL); + # returns here if no voicemail server is configured + sl_send_reply("404", "No voicemail service"); + exit; + } + +#!ifdef WITH_PRESENCE +#!ifdef WITH_MSGREBUILD + # apply changes in case the request headers or body were modified + msg_apply_changes(); +#!endif + if (!t_newtran()) { + sl_reply_error(); + exit; + } + + if(is_method("PUBLISH")) { + handle_publish(); + t_release(); + } else if(is_method("SUBSCRIBE")) { + handle_subscribe(); + t_release(); + } + exit; +#!endif + + # if presence enabled, this part will not be executed + if (is_method("PUBLISH") || $rU==$null) { + sl_send_reply("404", "Not here"); + exit; + } + return; +} + +# IP authorization and user authentication +route[AUTH] { +#!ifdef WITH_AUTH + +#!ifdef WITH_IPAUTH + if((!is_method("REGISTER")) && allow_source_address()) { + # source IP allowed + return; + } +#!endif + + if (is_method("REGISTER") || from_uri==myself) { + # authenticate requests + if (!auth_check("$fd", "subscriber", "1")) { + auth_challenge("$fd", "0"); + exit; + } + # user authenticated - remove auth header + if(!is_method("REGISTER|PUBLISH")) + consume_credentials(); + } + # if caller is not local subscriber, then check if it calls + # a local destination, otherwise deny, not an open relay here + if (from_uri!=myself && uri!=myself) { + sl_send_reply("403","Not relaying"); + exit; + } + +#!else + + # authentication not enabled - do not relay at all to foreign networks + if(uri!=myself) { + sl_send_reply("403","Not relaying"); + exit; + } + +#!endif + return; +} + +# Caller NAT detection +route[NATDETECT] { +#!ifdef WITH_NAT + if (nat_uac_test("19")) { + if (is_method("REGISTER")) { + fix_nated_register(); + } else { + if(is_first_hop()) { + set_contact_alias(); + } + } + setflag(FLT_NATS); + } +#!endif + return; +} + +# RTPProxy control and signaling updates for NAT traversal +route[NATMANAGE] { +#!ifdef WITH_NAT + if (is_request()) { + if(has_totag()) { + if(check_route_param("nat=yes")) { + setbflag(FLB_NATB); + } + } + } + if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) return; + +#!ifdef WITH_RTPENGINE + if(nat_uac_test("8")) { + rtpengine_manage("SIP-source-address replace-origin replace-session-connection"); + } else { + rtpengine_manage("replace-origin replace-session-connection"); + } +#!else + if(nat_uac_test("8")) { + rtpproxy_manage("co"); + } else { + rtpproxy_manage("cor"); + } +#!endif + + if (is_request()) { + if (!has_totag()) { + if(t_is_branch_route()) { + add_rr_param(";nat=yes"); + } + } + } + if (is_reply()) { + if(isbflagset(FLB_NATB)) { + if(is_first_hop()) + set_contact_alias(); + } + } + + if(isbflagset(FLB_NATB)) { + # no connect message in a dialog involving NAT traversal + if (is_request()) { + if(has_totag()) { + set_forward_no_connect(); + } + } + } +#!endif + return; +} + +# URI update for dialog requests +route[DLGURI] { +#!ifdef WITH_NAT + if(!isdsturiset()) { + handle_ruri_alias(); + } +#!endif + return; +} + +# Routing to foreign domains +route[SIPOUT] { + if (uri==myself) return; + + append_hf("P-Hint: outbound\r\n"); + route(RELAY); + exit; +} + +# PSTN GW routing +route[PSTN] { +#!ifdef WITH_PSTN + # check if PSTN GW IP is defined + if (strempty($sel(cfg_get.pstn.gw_ip))) { + xlog("SCRIPT: PSTN routing enabled but pstn.gw_ip not defined\n"); + return; + } + + # route to PSTN dialed numbers starting with '+' or '00' + # (international format) + # - update the condition to match your dialing rules for PSTN routing + if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$")) return; + + # only local users allowed to call + if(from_uri!=myself) { + sl_send_reply("403", "Not Allowed"); + exit; + } + + # normalize target number for pstn gateway + # - convert leading 00 to + + if (starts_with("$rU", "00")) { + strip(2); + prefix("+"); + } + + if (strempty($sel(cfg_get.pstn.gw_port))) { + $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip); + } else { + $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip) + ":" + + $sel(cfg_get.pstn.gw_port); + } + + route(RELAY); + exit; +#!endif + + return; +} + +# JSONRPC over HTTP(S) routing +#!ifdef WITH_JSONRPC +event_route[xhttp:request] { + set_reply_close(); + set_reply_no_connect(); + if(src_ip!=127.0.0.1) { + xhttp_reply("403", "Forbidden", "text/html", + "Not allowed from $si"); + exit; + } + if ($hu =~ "^/RPC") { + jsonrpc_dispatch(); + exit; + } + + xhttp_reply("200", "OK", "text/html", + "Wrong URL $hu"); + exit; +} +#!endif + +# Routing to voicemail server +route[TOVOICEMAIL] { +#!ifdef WITH_VOICEMAIL + if(!is_method("INVITE|SUBSCRIBE")) return; + + # check if VoiceMail server IP is defined + if (strempty($sel(cfg_get.voicemail.srv_ip))) { + xlog("SCRIPT: VoiceMail routing enabled but IP not defined\n"); + return; + } + if(is_method("INVITE")) { + if($avp(oexten)==$null) return; + + $ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip) + + ":" + $sel(cfg_get.voicemail.srv_port); + } else { + if($rU==$null) return; + + $ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip) + + ":" + $sel(cfg_get.voicemail.srv_port); + } + route(RELAY); + exit; +#!endif + + return; +} + +# Manage outgoing branches +branch_route[MANAGE_BRANCH] { + xdbg("new branch [$T_branch_idx] to $ru\n"); + route(NATMANAGE); +} + +# Manage incoming replies +reply_route { + if(!sanity_check("17604", "6")) { + xlog("Malformed SIP response from $si:$sp\n"); + drop; + } +} + +# Manage incoming replies in transaction context +onreply_route[MANAGE_REPLY] { + xdbg("incoming reply\n"); + if(status=~"[12][0-9][0-9]") { + route(NATMANAGE); + } +} + +# Manage failure routing cases +failure_route[MANAGE_FAILURE] { + route(NATMANAGE); + + if (t_is_canceled()) exit; + +#!ifdef WITH_BLOCK3XX + # block call redirect based on 3xx replies. + if (t_check_status("3[0-9][0-9]")) { + t_reply("404","Not found"); + exit; + } +#!endif + +#!ifdef WITH_BLOCK401407 + # block call redirect based on 401, 407 replies. + if (t_check_status("401|407")) { + t_reply("404","Not found"); + exit; + } +#!endif + +#!ifdef WITH_VOICEMAIL + # serial forking + # - route to voicemail on busy or no answer (timeout) + if (t_check_status("486|408")) { + $du = $null; + route(TOVOICEMAIL); + exit; + } +#!endif +} + +# Dispatch requests +route[DISPATCH] { + # round robin dispatching on gateways group '1' + if(!ds_select_dst("1", "4")) { + send_reply("404", "No destination"); + exit; + } + xdbg("--- SCRIPT: going to <$ru> via <$du> (attrs: $xavp(_dsdst_=>attrs))\n"); + t_on_failure("RTF_DISPATCH"); + route(RELAY); + exit; +} + +# Try next destionations in failure route +failure_route[RTF_DISPATCH] { + if (t_is_canceled()) { + exit; + } + # next DST - only for 500 or local timeout + if (t_check_status("500") + or (t_branch_timeout() and !t_branch_replied())) { + if(ds_next_dst()) { + xdbg("--- SCRIPT: retrying to <$ru> via <$du> (attrs: $xavp(_dsdst_=>attrs))\n"); + t_on_failure("RTF_DISPATCH"); + route(RELAY); + exit; + } + } +} diff --git a/kamailio/kamailio.cfg.bak b/kamailio/kamailio.cfg.bak index be71dbb..063b24d 100644 --- a/kamailio/kamailio.cfg.bak +++ b/kamailio/kamailio.cfg.bak @@ -1,1054 +1,1054 @@ -#!KAMAILIO -# -# Kamailio SIP Server v5.5 - default configuration script -# - web: https://www.kamailio.org -# - git: https://github.com/kamailio/kamailio -# -# Direct your questions about this file to: -# -# Refer to the Core CookBook at https://www.kamailio.org/wiki/ -# for an explanation of possible statements, functions and parameters. -# -# Note: the comments can be: -# - lines starting with #, but not the pre-processor directives, -# which start with #!, like #!define, #!ifdef, #!endif, #!else, #!trydef, -# #!subst, #!substdef, ... -# - lines starting with // -# - blocks enclosed in between /* */ -# Note: the config performs symmetric SIP signaling -# - it sends the reply to the source address of the request -# - remove the use of force_rport() for asymmetric SIP signaling -# -# Several features can be enabled using '#!define WITH_FEATURE' directives: -# -# *** To run in debug mode: -# - define WITH_DEBUG -# - debug level increased to 3, logs still sent to syslog -# - debugger module loaded with cfgtrace endabled -# -# *** To enable mysql: -# - define WITH_MYSQL -# -# *** To enable authentication execute: -# - enable mysql -# - define WITH_AUTH -# - add users using 'kamctl' or 'kamcli' -# -# *** To enable IP authentication execute: -# - enable mysql -# - enable authentication -# - define WITH_IPAUTH -# - add IP addresses with group id '1' to 'address' table -# -# *** To enable persistent user location execute: -# - enable mysql -# - define WITH_USRLOCDB -# -# *** To enable presence server execute: -# - enable mysql -# - define WITH_PRESENCE -# - if modified headers or body in config must be used by presence handling: -# - define WITH_MSGREBUILD -# -# *** To enable nat traversal execute: -# - define WITH_NAT -# - option for NAT SIP OPTIONS keepalives: WITH_NATSIPPING -# - install RTPProxy: http://www.rtpproxy.org -# - start RTPProxy: -# rtpproxy -l _your_public_ip_ -s udp:localhost:7722 -# -# *** To use RTPEngine (instead of RTPProxy) for nat traversal execute: -# - define WITH_RTPENGINE -# - install RTPEngine: https://github.com/sipwise/rtpengine -# - start RTPEngine: -# rtpengine --listen-ng=127.0.0.1:2223 ... -# -# *** To enable PSTN gateway routing execute: -# - define WITH_PSTN -# - set the value of pstn.gw_ip -# - check route[PSTN] for regexp routing condition -# -# *** To enable database aliases lookup execute: -# - enable mysql -# - define WITH_ALIASDB -# -# *** To enable speed dial lookup execute: -# - enable mysql -# - define WITH_SPEEDDIAL -# -# *** To enable multi-domain support execute: -# - enable mysql -# - define WITH_MULTIDOMAIN -# -# *** To enable TLS support execute: -# - adjust CFGDIR/tls.cfg as needed -# - define WITH_TLS -# -# *** To enable JSONRPC over HTTP(S) support execute: -# - define WITH_JSONRPC -# - adjust event_route[xhttp:request] for access policy -# -# *** 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 block 3XX redirect replies execute: -# - define WITH_BLOCK3XX -# -# *** To block 401 and 407 authentication replies execute: -# - define WITH_BLOCK401407 -# -# *** To enable VoiceMail routing execute: -# - define WITH_VOICEMAIL -# - set the value of voicemail.srv_ip -# - adjust the value of voicemail.srv_port -# -# *** To enhance accounting execute: -# - enable mysql -# - define WITH_ACCDB -# - add following columns to database -#!ifdef ACCDB_COMMENT - ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT ''; - ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT ''; - ALTER TABLE acc ADD COLUMN src_ip varchar(64) NOT NULL default ''; - ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT ''; - ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT ''; - ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT ''; - ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT ''; - ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT ''; - ALTER TABLE missed_calls ADD COLUMN src_ip varchar(64) NOT NULL default ''; - ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT ''; - ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT ''; - ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT ''; -#!endif - -####### Include Local Config If Exists ######### -import_file "kamailio-local.cfg" - -####### Defined Values ######### - -# *** Value defines - IDs used later in config -#!ifdef WITH_DEBUG -#!define DBGLEVEL 3 -#!else -#!define DBGLEVEL 2 -#!endif - -#!ifdef WITH_MYSQL -# - database URL - used to connect to database server by modules such -# as: auth_db, acc, usrloc, a.s.o. -#!trydef DBURL "mysql://kamailio:kamailiorw@localhost/kamailio" -#!endif - -#!ifdef WITH_MULTIDOMAIN -# - the value for 'use_domain' parameters -#!define MULTIDOMAIN 1 -#!else -#!define MULTIDOMAIN 0 -#!endif - -# - flags -# FLT_ - per transaction (message) flags -#!define FLT_ACC 1 -#!define FLT_ACCMISSED 2 -#!define FLT_ACCFAILED 3 -#!define FLT_NATS 5 - -# FLB_ - per branch flags -#!define FLB_NATB 6 -#!define FLB_NATSIPPING 7 - -####### Global Parameters ######### - -/* LOG Levels: 3=DBG, 2=INFO, 1=NOTICE, 0=WARN, -1=ERR, ... */ -debug=DBGLEVEL - -/* set to 'yes' to print log messages to terminal or use '-E' cli option */ -log_stderror=no - -memdbg=5 -memlog=5 - -log_facility=LOG_LOCAL0 -log_prefix="{$mt $hdr(CSeq) $ci} " - -/* number of SIP routing processes for each UDP socket - * - value inherited by tcp_children and sctp_children when not set explicitely */ -children=8 - -/* uncomment the next line to disable TCP (default on) */ -# disable_tcp=yes - -/* number of SIP routing processes for all TCP/TLS sockets */ -# tcp_children=8 - -/* uncomment the next line to disable the auto discovery of local aliases - * based on reverse DNS on IPs (default on) */ -# auto_aliases=no - -/* add local domain aliases - it can be set many times */ -# alias="sip.mydomain.com" - -/* listen sockets - if none set, Kamailio binds to all local IP addresses - * - basic prototype (full prototype can be found in Wiki - Core Cookbook): - * listen=[proto]:[localip]:[lport] advertise [publicip]:[pport] - * - it can be set many times to add more sockets to listen to */ -# listen=udp:10.0.0.10:5060 - -/* 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=3605 - -/* upper limit for TCP connections (it includes the TLS connections) */ -tcp_max_connections=2048 - -#!ifdef WITH_JSONRPC -tcp_accept_no_cl=yes -#!endif - -#!ifdef WITH_TLS -enable_tls=yes - -/* upper limit for TLS connections */ -tls_max_connections=2048 -#!endif - -/* set it to yes to enable sctp and load sctp.so module */ -enable_sctp=no - -####### Custom Parameters ######### - -/* These parameters can be modified runtime via RPC interface - * - see the documentation of 'cfg_rpc' module. - * - * Format: group.id = value 'desc' description - * Access: $sel(cfg_get.group.id) or @cfg_get.group.id */ - -#!ifdef WITH_PSTN -/* PSTN GW Routing - * - * - pstn.gw_ip: valid IP or hostname as string value, example: - * pstn.gw_ip = "10.0.0.101" desc "My PSTN GW Address" - * - * - by default is empty to avoid misrouting */ -pstn.gw_ip = "" desc "PSTN GW Address" -pstn.gw_port = "" desc "PSTN GW Port" -#!endif - -#!ifdef WITH_VOICEMAIL -/* VoiceMail Routing on offline, busy or no answer - * - * - by default Voicemail server IP is empty to avoid misrouting */ -voicemail.srv_ip = "" desc "VoiceMail IP Address" -voicemail.srv_port = "5060" desc "VoiceMail Port" -#!endif - -####### Modules Section ######## - -/* set paths to location of modules */ -# mpath="/usr/local/lib/kamailio/modules/" - -#!ifdef WITH_MYSQL -loadmodule "db_mysql.so" -#!endif - -#!ifdef WITH_JSONRPC -loadmodule "xhttp.so" -#!endif -loadmodule "jsonrpcs.so" -loadmodule "kex.so" -loadmodule "corex.so" -loadmodule "tm.so" -loadmodule "tmx.so" -loadmodule "sl.so" -loadmodule "rr.so" -loadmodule "pv.so" -loadmodule "maxfwd.so" -loadmodule "usrloc.so" -loadmodule "registrar.so" -loadmodule "textops.so" -loadmodule "textopsx.so" -loadmodule "siputils.so" -loadmodule "xlog.so" -loadmodule "sanity.so" -loadmodule "ctl.so" -loadmodule "cfg_rpc.so" -loadmodule "acc.so" -loadmodule "counters.so" - -#!ifdef WITH_AUTH -loadmodule "auth.so" -loadmodule "auth_db.so" -#!ifdef WITH_IPAUTH -loadmodule "permissions.so" -#!endif -#!endif - -#!ifdef WITH_ALIASDB -loadmodule "alias_db.so" -#!endif - -#!ifdef WITH_SPEEDDIAL -loadmodule "speeddial.so" -#!endif - -#!ifdef WITH_MULTIDOMAIN -loadmodule "domain.so" -#!endif - -#!ifdef WITH_PRESENCE -loadmodule "presence.so" -loadmodule "presence_xml.so" -#!endif - -#!ifdef WITH_NAT -loadmodule "nathelper.so" -#!ifdef WITH_RTPENGINE -loadmodule "rtpengine.so" -#!else -loadmodule "rtpproxy.so" -#!endif -#!endif - -#!ifdef WITH_TLS -loadmodule "tls.so" -#!endif - -#!ifdef WITH_ANTIFLOOD -loadmodule "htable.so" -loadmodule "pike.so" -#!endif - -#!ifdef WITH_DEBUG -loadmodule "debugger.so" -#!endif - -# ----------------- setting module-specific parameters --------------- - - -# ----- jsonrpcs params ----- -modparam("jsonrpcs", "pretty_format", 1) -/* set the path to RPC fifo control file */ -# modparam("jsonrpcs", "fifo_name", "/run/kamailio/kamailio_rpc.fifo") -/* set the path to RPC unix socket control file */ -# modparam("jsonrpcs", "dgram_socket", "/run/kamailio/kamailio_rpc.sock") -#!ifdef WITH_JSONRPC -modparam("jsonrpcs", "transport", 7) -#!endif - -# ----- ctl params ----- -/* set the path to RPC unix socket control file */ -# modparam("ctl", "binrpc", "unix:/run/kamailio/kamailio_ctl") - -# ----- sanity params ----- -modparam("sanity", "autodrop", 0) - -# ----- tm params ----- -# auto-discard branches from previous serial forking leg -modparam("tm", "failure_reply_mode", 3) -# default retransmission timeout: 30sec -modparam("tm", "fr_timer", 30000) -# default invite retransmission timeout after 1xx: 120sec -modparam("tm", "fr_inv_timer", 120000) - -# ----- rr params ----- -# set next param to 1 to add value to ;lr param (helps with some UAs) -modparam("rr", "enable_full_lr", 0) -# do not append from tag to the RR (no need for this script) -modparam("rr", "append_fromtag", 0) - -# ----- registrar params ----- -modparam("registrar", "method_filtering", 1) -/* uncomment the next line to disable parallel forking via location */ -# modparam("registrar", "append_branches", 0) -/* uncomment the next line not to allow more than 10 contacts per AOR */ -# modparam("registrar", "max_contacts", 10) -/* max value for expires of registrations */ -modparam("registrar", "max_expires", 3600) -/* set it to 1 to enable GRUU */ -modparam("registrar", "gruu_enabled", 0) -/* set it to 0 to disable Path handling */ -modparam("registrar", "use_path", 1) -/* save Path even if not listed in Supported header */ -modparam("registrar", "path_mode", 0) - -# ----- acc params ----- -/* what special events should be accounted ? */ -modparam("acc", "early_media", 0) -modparam("acc", "report_ack", 0) -modparam("acc", "report_cancels", 0) -/* by default ww do not adjust the direct of the sequential requests. - * if you enable this parameter, be sure the enable "append_fromtag" - * in "rr" module */ -modparam("acc", "detect_direction", 0) -/* account triggers (flags) */ -modparam("acc", "log_flag", FLT_ACC) -modparam("acc", "log_missed_flag", FLT_ACCMISSED) -modparam("acc", "log_extra", - "src_user=$fU;src_domain=$fd;src_ip=$si;" - "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") -modparam("acc", "failed_transaction_flag", FLT_ACCFAILED) -/* enhanced DB accounting */ -#!ifdef WITH_ACCDB -modparam("acc", "db_flag", FLT_ACC) -modparam("acc", "db_missed_flag", FLT_ACCMISSED) -modparam("acc", "db_url", DBURL) -modparam("acc", "db_extra", - "src_user=$fU;src_domain=$fd;src_ip=$si;" - "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") -#!endif - -# ----- usrloc params ----- -modparam("usrloc", "timer_interval", 60) -modparam("usrloc", "timer_procs", 1) -modparam("usrloc", "use_domain", MULTIDOMAIN) -/* enable DB persistency for location entries */ -#!ifdef WITH_USRLOCDB -modparam("usrloc", "db_url", DBURL) -modparam("usrloc", "db_mode", 2) -#!endif - -# ----- auth_db params ----- -#!ifdef WITH_AUTH -modparam("auth_db", "db_url", DBURL) -modparam("auth_db", "calculate_ha1", yes) -modparam("auth_db", "password_column", "password") -modparam("auth_db", "load_credentials", "") -modparam("auth_db", "use_domain", MULTIDOMAIN) - -# ----- permissions params ----- -#!ifdef WITH_IPAUTH -modparam("permissions", "db_url", DBURL) -modparam("permissions", "load_backends", 1) -#!endif - -#!endif - -# ----- alias_db params ----- -#!ifdef WITH_ALIASDB -modparam("alias_db", "db_url", DBURL) -modparam("alias_db", "use_domain", MULTIDOMAIN) -#!endif - -# ----- speeddial params ----- -#!ifdef WITH_SPEEDDIAL -modparam("speeddial", "db_url", DBURL) -modparam("speeddial", "use_domain", MULTIDOMAIN) -#!endif - -# ----- domain params ----- -#!ifdef WITH_MULTIDOMAIN -modparam("domain", "db_url", DBURL) -/* register callback to match myself condition with domains list */ -modparam("domain", "register_myself", 1) -#!endif - -#!ifdef WITH_PRESENCE -# ----- presence params ----- -modparam("presence", "db_url", DBURL) - -# ----- presence_xml params ----- -modparam("presence_xml", "db_url", DBURL) -modparam("presence_xml", "force_active", 1) -#!endif - -#!ifdef WITH_NAT -#!ifdef WITH_RTPENGINE -# ----- rtpengine params ----- -modparam("rtpengine", "rtpengine_sock", "udp:127.0.0.1:2223") -#!else -# ----- rtpproxy params ----- -modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722") -#!endif -# ----- nathelper params ----- -modparam("nathelper", "natping_interval", 30) -modparam("nathelper", "ping_nated_only", 1) -modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) -modparam("nathelper", "sipping_from", "sip:pinger@kamailio.org") - -# params needed for NAT traversal in other modules -modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)") -modparam("usrloc", "nat_bflag", FLB_NATB) -#!endif - -#!ifdef WITH_TLS -# ----- tls params ----- -modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg") -#!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;") -#!endif - -#!ifdef WITH_DEBUG -# ----- debugger params ----- -modparam("debugger", "cfgtrace", 1) -modparam("debugger", "log_level_name", "exec") -#!endif - -####### Routing Logic ######## - - -/* Main SIP request routing logic - * - processing of any incoming SIP request starts with this route - * - note: this is the same as route { ... } */ -request_route { - - # per request initial checks - route(REQINIT); - - # NAT detection - route(NATDETECT); - - # CANCEL processing - if (is_method("CANCEL")) { - if (t_check_trans()) { - route(RELAY); - } - exit; - } - - # handle retransmissions - if (!is_method("ACK")) { - if(t_precheck_trans()) { - t_check_trans(); - exit; - } - t_check_trans(); - } - - # handle requests within SIP dialogs - route(WITHINDLG); - - ### only initial requests (no To tag) - - # authentication - route(AUTH); - - # record routing for dialog forming requests (in case they are routed) - # - remove preloaded route headers - remove_hf("Route"); - if (is_method("INVITE|SUBSCRIBE")) { - record_route(); - } - - # account only INVITEs - if (is_method("INVITE")) { - setflag(FLT_ACC); # do accounting - } - - # dispatch requests to foreign domains - route(SIPOUT); - - ### requests for my local domains - - # handle presence related requests - route(PRESENCE); - - # handle registrations - route(REGISTRAR); - - if ($rU==$null) { - # request with no Username in RURI - sl_send_reply("484","Address Incomplete"); - exit; - } - - # dispatch destinations to PSTN - route(PSTN); - - # user location service - route(LOCATION); -} - -# Wrapper for relaying requests -route[RELAY] { - - # enable additional event routes for forwarded requests - # - serial forking, RTP relaying handling, a.s.o. - if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) { - if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH"); - } - if (is_method("INVITE|SUBSCRIBE|UPDATE")) { - if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY"); - } - if (is_method("INVITE")) { - if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE"); - } - - if (!t_relay()) { - sl_reply_error(); - } - exit; -} - -# Per SIP request initial checks -route[REQINIT] { - # no connect for sending replies - set_reply_no_connect(); - # enforce symmetric signaling - # - send back replies to the source address of request - force_rport(); - -#!ifdef WITH_ANTIFLOOD - # flood detection 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(src_ip!=myself) { - if($sht(ipban=>$si)!=$null) { - # ip is already blocked - xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n"); - exit; - } - if (!pike_check_req()) { - xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n"); - $sht(ipban=>$si) = 1; - exit; - } - } -#!endif - if($ua =~ "friendly|scanner|sipcli|sipvicious|VaxSIPUserAgent") { - # silent drop for scanners - uncomment next line if want to reply - # sl_send_reply("200", "OK"); - exit; - } - - if (!mf_process_maxfwd_header("10")) { - sl_send_reply("483","Too Many Hops"); - exit; - } - - if(is_method("OPTIONS") && uri==myself && $rU==$null) { - sl_send_reply("200","Keepalive"); - exit; - } - - if(!sanity_check("17895", "7")) { - xlog("Malformed SIP request from $si:$sp\n"); - exit; - } -} - -# Handle requests within SIP dialogs -route[WITHINDLG] { - if (!has_totag()) return; - - # sequential request withing a dialog should - # take the path determined by record-routing - if (loose_route()) { - route(DLGURI); - if (is_method("BYE")) { - setflag(FLT_ACC); # do accounting ... - setflag(FLT_ACCFAILED); # ... even if the transaction fails - } else if ( is_method("ACK") ) { - # ACK is forwarded statelessly - route(NATMANAGE); - } else if ( is_method("NOTIFY") ) { - # Add Record-Route for in-dialog NOTIFY as per RFC 6665. - record_route(); - } - route(RELAY); - exit; - } - - if (is_method("SUBSCRIBE") && uri == myself) { - # in-dialog subscribe requests - route(PRESENCE); - exit; - } - if ( is_method("ACK") ) { - if ( t_check_trans() ) { - # no loose-route, but stateful ACK; - # must be an ACK after a 487 - # or e.g. 404 from upstream server - route(RELAY); - exit; - } else { - # ACK without matching transaction ... ignore and discard - exit; - } - } - sl_send_reply("404","Not here"); - exit; -} - -# Handle SIP registrations -route[REGISTRAR] { - if (!is_method("REGISTER")) return; - - if(isflagset(FLT_NATS)) { - setbflag(FLB_NATB); -#!ifdef WITH_NATSIPPING - # do SIP NAT pinging - setbflag(FLB_NATSIPPING); -#!endif - } - if (!save("location")) { - sl_reply_error(); - } - exit; -} - -# User location service -route[LOCATION] { - -#!ifdef WITH_SPEEDDIAL - # search for short dialing - 2-digit extension - if($rU=~"^[0-9][0-9]$") { - if(sd_lookup("speed_dial")) { - route(SIPOUT); - } - } -#!endif - -#!ifdef WITH_ALIASDB - # search in DB-based aliases - if(alias_db_lookup("dbaliases")) { - route(SIPOUT); - } -#!endif - - $avp(oexten) = $rU; - if (!lookup("location")) { - $var(rc) = $rc; - route(TOVOICEMAIL); - t_newtran(); - switch ($var(rc)) { - case -1: - case -3: - send_reply("404", "Not Found"); - exit; - case -2: - send_reply("405", "Method Not Allowed"); - exit; - } - } - - # when routing via usrloc, log the missed calls also - if (is_method("INVITE")) { - setflag(FLT_ACCMISSED); - } - - route(RELAY); - exit; -} - -# Presence server processing -route[PRESENCE] { - if(!is_method("PUBLISH|SUBSCRIBE")) return; - - if(is_method("SUBSCRIBE") && $hdr(Event)=="message-summary") { - route(TOVOICEMAIL); - # returns here if no voicemail server is configured - sl_send_reply("404", "No voicemail service"); - exit; - } - -#!ifdef WITH_PRESENCE -#!ifdef WITH_MSGREBUILD - # apply changes in case the request headers or body were modified - msg_apply_changes(); -#!endif - if (!t_newtran()) { - sl_reply_error(); - exit; - } - - if(is_method("PUBLISH")) { - handle_publish(); - t_release(); - } else if(is_method("SUBSCRIBE")) { - handle_subscribe(); - t_release(); - } - exit; -#!endif - - # if presence enabled, this part will not be executed - if (is_method("PUBLISH") || $rU==$null) { - sl_send_reply("404", "Not here"); - exit; - } - return; -} - -# IP authorization and user authentication -route[AUTH] { -#!ifdef WITH_AUTH - -#!ifdef WITH_IPAUTH - if((!is_method("REGISTER")) && allow_source_address()) { - # source IP allowed - return; - } -#!endif - - if (is_method("REGISTER") || from_uri==myself) { - # authenticate requests - if (!auth_check("$fd", "subscriber", "1")) { - auth_challenge("$fd", "0"); - exit; - } - # user authenticated - remove auth header - if(!is_method("REGISTER|PUBLISH")) - consume_credentials(); - } - # if caller is not local subscriber, then check if it calls - # a local destination, otherwise deny, not an open relay here - if (from_uri!=myself && uri!=myself) { - sl_send_reply("403","Not relaying"); - exit; - } - -#!else - - # authentication not enabled - do not relay at all to foreign networks - if(uri!=myself) { - sl_send_reply("403","Not relaying"); - exit; - } - -#!endif - return; -} - -# Caller NAT detection -route[NATDETECT] { -#!ifdef WITH_NAT - if (nat_uac_test("19")) { - if (is_method("REGISTER")) { - fix_nated_register(); - } else { - if(is_first_hop()) { - set_contact_alias(); - } - } - setflag(FLT_NATS); - } -#!endif - return; -} - -# RTPProxy control and signaling updates for NAT traversal -route[NATMANAGE] { -#!ifdef WITH_NAT - if (is_request()) { - if(has_totag()) { - if(check_route_param("nat=yes")) { - setbflag(FLB_NATB); - } - } - } - if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) return; - -#!ifdef WITH_RTPENGINE - if(nat_uac_test("8")) { - rtpengine_manage("SIP-source-address replace-origin replace-session-connection"); - } else { - rtpengine_manage("replace-origin replace-session-connection"); - } -#!else - if(nat_uac_test("8")) { - rtpproxy_manage("co"); - } else { - rtpproxy_manage("cor"); - } -#!endif - - if (is_request()) { - if (!has_totag()) { - if(t_is_branch_route()) { - add_rr_param(";nat=yes"); - } - } - } - if (is_reply()) { - if(isbflagset(FLB_NATB)) { - if(is_first_hop()) - set_contact_alias(); - } - } - - if(isbflagset(FLB_NATB)) { - # no connect message in a dialog involving NAT traversal - if (is_request()) { - if(has_totag()) { - set_forward_no_connect(); - } - } - } -#!endif - return; -} - -# URI update for dialog requests -route[DLGURI] { -#!ifdef WITH_NAT - if(!isdsturiset()) { - handle_ruri_alias(); - } -#!endif - return; -} - -# Routing to foreign domains -route[SIPOUT] { - if (uri==myself) return; - - append_hf("P-Hint: outbound\r\n"); - route(RELAY); - exit; -} - -# PSTN GW routing -route[PSTN] { -#!ifdef WITH_PSTN - # check if PSTN GW IP is defined - if (strempty($sel(cfg_get.pstn.gw_ip))) { - xlog("SCRIPT: PSTN routing enabled but pstn.gw_ip not defined\n"); - return; - } - - # route to PSTN dialed numbers starting with '+' or '00' - # (international format) - # - update the condition to match your dialing rules for PSTN routing - if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$")) return; - - # only local users allowed to call - if(from_uri!=myself) { - sl_send_reply("403", "Not Allowed"); - exit; - } - - # normalize target number for pstn gateway - # - convert leading 00 to + - if (starts_with("$rU", "00")) { - strip(2); - prefix("+"); - } - - if (strempty($sel(cfg_get.pstn.gw_port))) { - $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip); - } else { - $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip) + ":" - + $sel(cfg_get.pstn.gw_port); - } - - route(RELAY); - exit; -#!endif - - return; -} - -# JSONRPC over HTTP(S) routing -#!ifdef WITH_JSONRPC -event_route[xhttp:request] { - set_reply_close(); - set_reply_no_connect(); - if(src_ip!=127.0.0.1) { - xhttp_reply("403", "Forbidden", "text/html", - "Not allowed from $si"); - exit; - } - if ($hu =~ "^/RPC") { - jsonrpc_dispatch(); - exit; - } - - xhttp_reply("200", "OK", "text/html", - "Wrong URL $hu"); - exit; -} -#!endif - -# Routing to voicemail server -route[TOVOICEMAIL] { -#!ifdef WITH_VOICEMAIL - if(!is_method("INVITE|SUBSCRIBE")) return; - - # check if VoiceMail server IP is defined - if (strempty($sel(cfg_get.voicemail.srv_ip))) { - xlog("SCRIPT: VoiceMail routing enabled but IP not defined\n"); - return; - } - if(is_method("INVITE")) { - if($avp(oexten)==$null) return; - - $ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip) - + ":" + $sel(cfg_get.voicemail.srv_port); - } else { - if($rU==$null) return; - - $ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip) - + ":" + $sel(cfg_get.voicemail.srv_port); - } - route(RELAY); - exit; -#!endif - - return; -} - -# Manage outgoing branches -branch_route[MANAGE_BRANCH] { - xdbg("new branch [$T_branch_idx] to $ru\n"); - route(NATMANAGE); -} - -# Manage incoming replies -reply_route { - if(!sanity_check("17604", "6")) { - xlog("Malformed SIP response from $si:$sp\n"); - drop; - } -} - -# Manage incoming replies in transaction context -onreply_route[MANAGE_REPLY] { - xdbg("incoming reply\n"); - if(status=~"[12][0-9][0-9]") { - route(NATMANAGE); - } -} - -# Manage failure routing cases -failure_route[MANAGE_FAILURE] { - route(NATMANAGE); - - if (t_is_canceled()) exit; - -#!ifdef WITH_BLOCK3XX - # block call redirect based on 3xx replies. - if (t_check_status("3[0-9][0-9]")) { - t_reply("404","Not found"); - exit; - } -#!endif - -#!ifdef WITH_BLOCK401407 - # block call redirect based on 401, 407 replies. - if (t_check_status("401|407")) { - t_reply("404","Not found"); - exit; - } -#!endif - -#!ifdef WITH_VOICEMAIL - # serial forking - # - route to voicemail on busy or no answer (timeout) - if (t_check_status("486|408")) { - $du = $null; - route(TOVOICEMAIL); - exit; - } -#!endif -} +#!KAMAILIO +# +# Kamailio SIP Server v5.5 - default configuration script +# - web: https://www.kamailio.org +# - git: https://github.com/kamailio/kamailio +# +# Direct your questions about this file to: +# +# Refer to the Core CookBook at https://www.kamailio.org/wiki/ +# for an explanation of possible statements, functions and parameters. +# +# Note: the comments can be: +# - lines starting with #, but not the pre-processor directives, +# which start with #!, like #!define, #!ifdef, #!endif, #!else, #!trydef, +# #!subst, #!substdef, ... +# - lines starting with // +# - blocks enclosed in between /* */ +# Note: the config performs symmetric SIP signaling +# - it sends the reply to the source address of the request +# - remove the use of force_rport() for asymmetric SIP signaling +# +# Several features can be enabled using '#!define WITH_FEATURE' directives: +# +# *** To run in debug mode: +# - define WITH_DEBUG +# - debug level increased to 3, logs still sent to syslog +# - debugger module loaded with cfgtrace endabled +# +# *** To enable mysql: +# - define WITH_MYSQL +# +# *** To enable authentication execute: +# - enable mysql +# - define WITH_AUTH +# - add users using 'kamctl' or 'kamcli' +# +# *** To enable IP authentication execute: +# - enable mysql +# - enable authentication +# - define WITH_IPAUTH +# - add IP addresses with group id '1' to 'address' table +# +# *** To enable persistent user location execute: +# - enable mysql +# - define WITH_USRLOCDB +# +# *** To enable presence server execute: +# - enable mysql +# - define WITH_PRESENCE +# - if modified headers or body in config must be used by presence handling: +# - define WITH_MSGREBUILD +# +# *** To enable nat traversal execute: +# - define WITH_NAT +# - option for NAT SIP OPTIONS keepalives: WITH_NATSIPPING +# - install RTPProxy: http://www.rtpproxy.org +# - start RTPProxy: +# rtpproxy -l _your_public_ip_ -s udp:localhost:7722 +# +# *** To use RTPEngine (instead of RTPProxy) for nat traversal execute: +# - define WITH_RTPENGINE +# - install RTPEngine: https://github.com/sipwise/rtpengine +# - start RTPEngine: +# rtpengine --listen-ng=127.0.0.1:2223 ... +# +# *** To enable PSTN gateway routing execute: +# - define WITH_PSTN +# - set the value of pstn.gw_ip +# - check route[PSTN] for regexp routing condition +# +# *** To enable database aliases lookup execute: +# - enable mysql +# - define WITH_ALIASDB +# +# *** To enable speed dial lookup execute: +# - enable mysql +# - define WITH_SPEEDDIAL +# +# *** To enable multi-domain support execute: +# - enable mysql +# - define WITH_MULTIDOMAIN +# +# *** To enable TLS support execute: +# - adjust CFGDIR/tls.cfg as needed +# - define WITH_TLS +# +# *** To enable JSONRPC over HTTP(S) support execute: +# - define WITH_JSONRPC +# - adjust event_route[xhttp:request] for access policy +# +# *** 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 block 3XX redirect replies execute: +# - define WITH_BLOCK3XX +# +# *** To block 401 and 407 authentication replies execute: +# - define WITH_BLOCK401407 +# +# *** To enable VoiceMail routing execute: +# - define WITH_VOICEMAIL +# - set the value of voicemail.srv_ip +# - adjust the value of voicemail.srv_port +# +# *** To enhance accounting execute: +# - enable mysql +# - define WITH_ACCDB +# - add following columns to database +#!ifdef ACCDB_COMMENT + ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT ''; + ALTER TABLE acc ADD COLUMN src_ip varchar(64) NOT NULL default ''; + ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN src_ip varchar(64) NOT NULL default ''; + ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT ''; + ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT ''; +#!endif + +####### Include Local Config If Exists ######### +import_file "kamailio-local.cfg" + +####### Defined Values ######### + +# *** Value defines - IDs used later in config +#!ifdef WITH_DEBUG +#!define DBGLEVEL 3 +#!else +#!define DBGLEVEL 2 +#!endif + +#!ifdef WITH_MYSQL +# - database URL - used to connect to database server by modules such +# as: auth_db, acc, usrloc, a.s.o. +#!trydef DBURL "mysql://kamailio:kamailiorw@localhost/kamailio" +#!endif + +#!ifdef WITH_MULTIDOMAIN +# - the value for 'use_domain' parameters +#!define MULTIDOMAIN 1 +#!else +#!define MULTIDOMAIN 0 +#!endif + +# - flags +# FLT_ - per transaction (message) flags +#!define FLT_ACC 1 +#!define FLT_ACCMISSED 2 +#!define FLT_ACCFAILED 3 +#!define FLT_NATS 5 + +# FLB_ - per branch flags +#!define FLB_NATB 6 +#!define FLB_NATSIPPING 7 + +####### Global Parameters ######### + +/* LOG Levels: 3=DBG, 2=INFO, 1=NOTICE, 0=WARN, -1=ERR, ... */ +debug=DBGLEVEL + +/* set to 'yes' to print log messages to terminal or use '-E' cli option */ +log_stderror=no + +memdbg=5 +memlog=5 + +log_facility=LOG_LOCAL0 +log_prefix="{$mt $hdr(CSeq) $ci} " + +/* number of SIP routing processes for each UDP socket + * - value inherited by tcp_children and sctp_children when not set explicitely */ +children=8 + +/* uncomment the next line to disable TCP (default on) */ +# disable_tcp=yes + +/* number of SIP routing processes for all TCP/TLS sockets */ +# tcp_children=8 + +/* uncomment the next line to disable the auto discovery of local aliases + * based on reverse DNS on IPs (default on) */ +# auto_aliases=no + +/* add local domain aliases - it can be set many times */ +# alias="sip.mydomain.com" + +/* listen sockets - if none set, Kamailio binds to all local IP addresses + * - basic prototype (full prototype can be found in Wiki - Core Cookbook): + * listen=[proto]:[localip]:[lport] advertise [publicip]:[pport] + * - it can be set many times to add more sockets to listen to */ +# listen=udp:10.0.0.10:5060 + +/* 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=3605 + +/* upper limit for TCP connections (it includes the TLS connections) */ +tcp_max_connections=2048 + +#!ifdef WITH_JSONRPC +tcp_accept_no_cl=yes +#!endif + +#!ifdef WITH_TLS +enable_tls=yes + +/* upper limit for TLS connections */ +tls_max_connections=2048 +#!endif + +/* set it to yes to enable sctp and load sctp.so module */ +enable_sctp=no + +####### Custom Parameters ######### + +/* These parameters can be modified runtime via RPC interface + * - see the documentation of 'cfg_rpc' module. + * + * Format: group.id = value 'desc' description + * Access: $sel(cfg_get.group.id) or @cfg_get.group.id */ + +#!ifdef WITH_PSTN +/* PSTN GW Routing + * + * - pstn.gw_ip: valid IP or hostname as string value, example: + * pstn.gw_ip = "10.0.0.101" desc "My PSTN GW Address" + * + * - by default is empty to avoid misrouting */ +pstn.gw_ip = "" desc "PSTN GW Address" +pstn.gw_port = "" desc "PSTN GW Port" +#!endif + +#!ifdef WITH_VOICEMAIL +/* VoiceMail Routing on offline, busy or no answer + * + * - by default Voicemail server IP is empty to avoid misrouting */ +voicemail.srv_ip = "" desc "VoiceMail IP Address" +voicemail.srv_port = "5060" desc "VoiceMail Port" +#!endif + +####### Modules Section ######## + +/* set paths to location of modules */ +# mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules/" + +#!ifdef WITH_MYSQL +loadmodule "db_mysql.so" +#!endif + +#!ifdef WITH_JSONRPC +loadmodule "xhttp.so" +#!endif +loadmodule "jsonrpcs.so" +loadmodule "kex.so" +loadmodule "corex.so" +loadmodule "tm.so" +loadmodule "tmx.so" +loadmodule "sl.so" +loadmodule "rr.so" +loadmodule "pv.so" +loadmodule "maxfwd.so" +loadmodule "usrloc.so" +loadmodule "registrar.so" +loadmodule "textops.so" +loadmodule "textopsx.so" +loadmodule "siputils.so" +loadmodule "xlog.so" +loadmodule "sanity.so" +loadmodule "ctl.so" +loadmodule "cfg_rpc.so" +loadmodule "acc.so" +loadmodule "counters.so" + +#!ifdef WITH_AUTH +loadmodule "auth.so" +loadmodule "auth_db.so" +#!ifdef WITH_IPAUTH +loadmodule "permissions.so" +#!endif +#!endif + +#!ifdef WITH_ALIASDB +loadmodule "alias_db.so" +#!endif + +#!ifdef WITH_SPEEDDIAL +loadmodule "speeddial.so" +#!endif + +#!ifdef WITH_MULTIDOMAIN +loadmodule "domain.so" +#!endif + +#!ifdef WITH_PRESENCE +loadmodule "presence.so" +loadmodule "presence_xml.so" +#!endif + +#!ifdef WITH_NAT +loadmodule "nathelper.so" +#!ifdef WITH_RTPENGINE +loadmodule "rtpengine.so" +#!else +loadmodule "rtpproxy.so" +#!endif +#!endif + +#!ifdef WITH_TLS +loadmodule "tls.so" +#!endif + +#!ifdef WITH_ANTIFLOOD +loadmodule "htable.so" +loadmodule "pike.so" +#!endif + +#!ifdef WITH_DEBUG +loadmodule "debugger.so" +#!endif + +# ----------------- setting module-specific parameters --------------- + + +# ----- jsonrpcs params ----- +modparam("jsonrpcs", "pretty_format", 1) +/* set the path to RPC fifo control file */ +# modparam("jsonrpcs", "fifo_name", "/run/kamailio/kamailio_rpc.fifo") +/* set the path to RPC unix socket control file */ +# modparam("jsonrpcs", "dgram_socket", "/run/kamailio/kamailio_rpc.sock") +#!ifdef WITH_JSONRPC +modparam("jsonrpcs", "transport", 7) +#!endif + +# ----- ctl params ----- +/* set the path to RPC unix socket control file */ +# modparam("ctl", "binrpc", "unix:/run/kamailio/kamailio_ctl") + +# ----- sanity params ----- +modparam("sanity", "autodrop", 0) + +# ----- tm params ----- +# auto-discard branches from previous serial forking leg +modparam("tm", "failure_reply_mode", 3) +# default retransmission timeout: 30sec +modparam("tm", "fr_timer", 30000) +# default invite retransmission timeout after 1xx: 120sec +modparam("tm", "fr_inv_timer", 120000) + +# ----- rr params ----- +# set next param to 1 to add value to ;lr param (helps with some UAs) +modparam("rr", "enable_full_lr", 0) +# do not append from tag to the RR (no need for this script) +modparam("rr", "append_fromtag", 0) + +# ----- registrar params ----- +modparam("registrar", "method_filtering", 1) +/* uncomment the next line to disable parallel forking via location */ +# modparam("registrar", "append_branches", 0) +/* uncomment the next line not to allow more than 10 contacts per AOR */ +# modparam("registrar", "max_contacts", 10) +/* max value for expires of registrations */ +modparam("registrar", "max_expires", 3600) +/* set it to 1 to enable GRUU */ +modparam("registrar", "gruu_enabled", 0) +/* set it to 0 to disable Path handling */ +modparam("registrar", "use_path", 1) +/* save Path even if not listed in Supported header */ +modparam("registrar", "path_mode", 0) + +# ----- acc params ----- +/* what special events should be accounted ? */ +modparam("acc", "early_media", 0) +modparam("acc", "report_ack", 0) +modparam("acc", "report_cancels", 0) +/* by default ww do not adjust the direct of the sequential requests. + * if you enable this parameter, be sure the enable "append_fromtag" + * in "rr" module */ +modparam("acc", "detect_direction", 0) +/* account triggers (flags) */ +modparam("acc", "log_flag", FLT_ACC) +modparam("acc", "log_missed_flag", FLT_ACCMISSED) +modparam("acc", "log_extra", + "src_user=$fU;src_domain=$fd;src_ip=$si;" + "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") +modparam("acc", "failed_transaction_flag", FLT_ACCFAILED) +/* enhanced DB accounting */ +#!ifdef WITH_ACCDB +modparam("acc", "db_flag", FLT_ACC) +modparam("acc", "db_missed_flag", FLT_ACCMISSED) +modparam("acc", "db_url", DBURL) +modparam("acc", "db_extra", + "src_user=$fU;src_domain=$fd;src_ip=$si;" + "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd") +#!endif + +# ----- usrloc params ----- +modparam("usrloc", "timer_interval", 60) +modparam("usrloc", "timer_procs", 1) +modparam("usrloc", "use_domain", MULTIDOMAIN) +/* enable DB persistency for location entries */ +#!ifdef WITH_USRLOCDB +modparam("usrloc", "db_url", DBURL) +modparam("usrloc", "db_mode", 2) +#!endif + +# ----- auth_db params ----- +#!ifdef WITH_AUTH +modparam("auth_db", "db_url", DBURL) +modparam("auth_db", "calculate_ha1", yes) +modparam("auth_db", "password_column", "password") +modparam("auth_db", "load_credentials", "") +modparam("auth_db", "use_domain", MULTIDOMAIN) + +# ----- permissions params ----- +#!ifdef WITH_IPAUTH +modparam("permissions", "db_url", DBURL) +modparam("permissions", "load_backends", 1) +#!endif + +#!endif + +# ----- alias_db params ----- +#!ifdef WITH_ALIASDB +modparam("alias_db", "db_url", DBURL) +modparam("alias_db", "use_domain", MULTIDOMAIN) +#!endif + +# ----- speeddial params ----- +#!ifdef WITH_SPEEDDIAL +modparam("speeddial", "db_url", DBURL) +modparam("speeddial", "use_domain", MULTIDOMAIN) +#!endif + +# ----- domain params ----- +#!ifdef WITH_MULTIDOMAIN +modparam("domain", "db_url", DBURL) +/* register callback to match myself condition with domains list */ +modparam("domain", "register_myself", 1) +#!endif + +#!ifdef WITH_PRESENCE +# ----- presence params ----- +modparam("presence", "db_url", DBURL) + +# ----- presence_xml params ----- +modparam("presence_xml", "db_url", DBURL) +modparam("presence_xml", "force_active", 1) +#!endif + +#!ifdef WITH_NAT +#!ifdef WITH_RTPENGINE +# ----- rtpengine params ----- +modparam("rtpengine", "rtpengine_sock", "udp:127.0.0.1:2223") +#!else +# ----- rtpproxy params ----- +modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722") +#!endif +# ----- nathelper params ----- +modparam("nathelper", "natping_interval", 30) +modparam("nathelper", "ping_nated_only", 1) +modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) +modparam("nathelper", "sipping_from", "sip:pinger@kamailio.org") + +# params needed for NAT traversal in other modules +modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)") +modparam("usrloc", "nat_bflag", FLB_NATB) +#!endif + +#!ifdef WITH_TLS +# ----- tls params ----- +modparam("tls", "config", "/etc/kamailio/tls.cfg") +#!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;") +#!endif + +#!ifdef WITH_DEBUG +# ----- debugger params ----- +modparam("debugger", "cfgtrace", 1) +modparam("debugger", "log_level_name", "exec") +#!endif + +####### Routing Logic ######## + + +/* Main SIP request routing logic + * - processing of any incoming SIP request starts with this route + * - note: this is the same as route { ... } */ +request_route { + + # per request initial checks + route(REQINIT); + + # NAT detection + route(NATDETECT); + + # CANCEL processing + if (is_method("CANCEL")) { + if (t_check_trans()) { + route(RELAY); + } + exit; + } + + # handle retransmissions + if (!is_method("ACK")) { + if(t_precheck_trans()) { + t_check_trans(); + exit; + } + t_check_trans(); + } + + # handle requests within SIP dialogs + route(WITHINDLG); + + ### only initial requests (no To tag) + + # authentication + route(AUTH); + + # record routing for dialog forming requests (in case they are routed) + # - remove preloaded route headers + remove_hf("Route"); + if (is_method("INVITE|SUBSCRIBE")) { + record_route(); + } + + # account only INVITEs + if (is_method("INVITE")) { + setflag(FLT_ACC); # do accounting + } + + # dispatch requests to foreign domains + route(SIPOUT); + + ### requests for my local domains + + # handle presence related requests + route(PRESENCE); + + # handle registrations + route(REGISTRAR); + + if ($rU==$null) { + # request with no Username in RURI + sl_send_reply("484","Address Incomplete"); + exit; + } + + # dispatch destinations to PSTN + route(PSTN); + + # user location service + route(LOCATION); +} + +# Wrapper for relaying requests +route[RELAY] { + + # enable additional event routes for forwarded requests + # - serial forking, RTP relaying handling, a.s.o. + if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) { + if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH"); + } + if (is_method("INVITE|SUBSCRIBE|UPDATE")) { + if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY"); + } + if (is_method("INVITE")) { + if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE"); + } + + if (!t_relay()) { + sl_reply_error(); + } + exit; +} + +# Per SIP request initial checks +route[REQINIT] { + # no connect for sending replies + set_reply_no_connect(); + # enforce symmetric signaling + # - send back replies to the source address of request + force_rport(); + +#!ifdef WITH_ANTIFLOOD + # flood detection 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(src_ip!=myself) { + if($sht(ipban=>$si)!=$null) { + # ip is already blocked + xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n"); + exit; + } + if (!pike_check_req()) { + xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n"); + $sht(ipban=>$si) = 1; + exit; + } + } +#!endif + if($ua =~ "friendly|scanner|sipcli|sipvicious|VaxSIPUserAgent") { + # silent drop for scanners - uncomment next line if want to reply + # sl_send_reply("200", "OK"); + exit; + } + + if (!mf_process_maxfwd_header("10")) { + sl_send_reply("483","Too Many Hops"); + exit; + } + + if(is_method("OPTIONS") && uri==myself && $rU==$null) { + sl_send_reply("200","Keepalive"); + exit; + } + + if(!sanity_check("17895", "7")) { + xlog("Malformed SIP request from $si:$sp\n"); + exit; + } +} + +# Handle requests within SIP dialogs +route[WITHINDLG] { + if (!has_totag()) return; + + # sequential request withing a dialog should + # take the path determined by record-routing + if (loose_route()) { + route(DLGURI); + if (is_method("BYE")) { + setflag(FLT_ACC); # do accounting ... + setflag(FLT_ACCFAILED); # ... even if the transaction fails + } else if ( is_method("ACK") ) { + # ACK is forwarded statelessly + route(NATMANAGE); + } else if ( is_method("NOTIFY") ) { + # Add Record-Route for in-dialog NOTIFY as per RFC 6665. + record_route(); + } + route(RELAY); + exit; + } + + if (is_method("SUBSCRIBE") && uri == myself) { + # in-dialog subscribe requests + route(PRESENCE); + exit; + } + if ( is_method("ACK") ) { + if ( t_check_trans() ) { + # no loose-route, but stateful ACK; + # must be an ACK after a 487 + # or e.g. 404 from upstream server + route(RELAY); + exit; + } else { + # ACK without matching transaction ... ignore and discard + exit; + } + } + sl_send_reply("404","Not here"); + exit; +} + +# Handle SIP registrations +route[REGISTRAR] { + if (!is_method("REGISTER")) return; + + if(isflagset(FLT_NATS)) { + setbflag(FLB_NATB); +#!ifdef WITH_NATSIPPING + # do SIP NAT pinging + setbflag(FLB_NATSIPPING); +#!endif + } + if (!save("location")) { + sl_reply_error(); + } + exit; +} + +# User location service +route[LOCATION] { + +#!ifdef WITH_SPEEDDIAL + # search for short dialing - 2-digit extension + if($rU=~"^[0-9][0-9]$") { + if(sd_lookup("speed_dial")) { + route(SIPOUT); + } + } +#!endif + +#!ifdef WITH_ALIASDB + # search in DB-based aliases + if(alias_db_lookup("dbaliases")) { + route(SIPOUT); + } +#!endif + + $avp(oexten) = $rU; + if (!lookup("location")) { + $var(rc) = $rc; + route(TOVOICEMAIL); + t_newtran(); + switch ($var(rc)) { + case -1: + case -3: + send_reply("404", "Not Found"); + exit; + case -2: + send_reply("405", "Method Not Allowed"); + exit; + } + } + + # when routing via usrloc, log the missed calls also + if (is_method("INVITE")) { + setflag(FLT_ACCMISSED); + } + + route(RELAY); + exit; +} + +# Presence server processing +route[PRESENCE] { + if(!is_method("PUBLISH|SUBSCRIBE")) return; + + if(is_method("SUBSCRIBE") && $hdr(Event)=="message-summary") { + route(TOVOICEMAIL); + # returns here if no voicemail server is configured + sl_send_reply("404", "No voicemail service"); + exit; + } + +#!ifdef WITH_PRESENCE +#!ifdef WITH_MSGREBUILD + # apply changes in case the request headers or body were modified + msg_apply_changes(); +#!endif + if (!t_newtran()) { + sl_reply_error(); + exit; + } + + if(is_method("PUBLISH")) { + handle_publish(); + t_release(); + } else if(is_method("SUBSCRIBE")) { + handle_subscribe(); + t_release(); + } + exit; +#!endif + + # if presence enabled, this part will not be executed + if (is_method("PUBLISH") || $rU==$null) { + sl_send_reply("404", "Not here"); + exit; + } + return; +} + +# IP authorization and user authentication +route[AUTH] { +#!ifdef WITH_AUTH + +#!ifdef WITH_IPAUTH + if((!is_method("REGISTER")) && allow_source_address()) { + # source IP allowed + return; + } +#!endif + + if (is_method("REGISTER") || from_uri==myself) { + # authenticate requests + if (!auth_check("$fd", "subscriber", "1")) { + auth_challenge("$fd", "0"); + exit; + } + # user authenticated - remove auth header + if(!is_method("REGISTER|PUBLISH")) + consume_credentials(); + } + # if caller is not local subscriber, then check if it calls + # a local destination, otherwise deny, not an open relay here + if (from_uri!=myself && uri!=myself) { + sl_send_reply("403","Not relaying"); + exit; + } + +#!else + + # authentication not enabled - do not relay at all to foreign networks + if(uri!=myself) { + sl_send_reply("403","Not relaying"); + exit; + } + +#!endif + return; +} + +# Caller NAT detection +route[NATDETECT] { +#!ifdef WITH_NAT + if (nat_uac_test("19")) { + if (is_method("REGISTER")) { + fix_nated_register(); + } else { + if(is_first_hop()) { + set_contact_alias(); + } + } + setflag(FLT_NATS); + } +#!endif + return; +} + +# RTPProxy control and signaling updates for NAT traversal +route[NATMANAGE] { +#!ifdef WITH_NAT + if (is_request()) { + if(has_totag()) { + if(check_route_param("nat=yes")) { + setbflag(FLB_NATB); + } + } + } + if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) return; + +#!ifdef WITH_RTPENGINE + if(nat_uac_test("8")) { + rtpengine_manage("SIP-source-address replace-origin replace-session-connection"); + } else { + rtpengine_manage("replace-origin replace-session-connection"); + } +#!else + if(nat_uac_test("8")) { + rtpproxy_manage("co"); + } else { + rtpproxy_manage("cor"); + } +#!endif + + if (is_request()) { + if (!has_totag()) { + if(t_is_branch_route()) { + add_rr_param(";nat=yes"); + } + } + } + if (is_reply()) { + if(isbflagset(FLB_NATB)) { + if(is_first_hop()) + set_contact_alias(); + } + } + + if(isbflagset(FLB_NATB)) { + # no connect message in a dialog involving NAT traversal + if (is_request()) { + if(has_totag()) { + set_forward_no_connect(); + } + } + } +#!endif + return; +} + +# URI update for dialog requests +route[DLGURI] { +#!ifdef WITH_NAT + if(!isdsturiset()) { + handle_ruri_alias(); + } +#!endif + return; +} + +# Routing to foreign domains +route[SIPOUT] { + if (uri==myself) return; + + append_hf("P-Hint: outbound\r\n"); + route(RELAY); + exit; +} + +# PSTN GW routing +route[PSTN] { +#!ifdef WITH_PSTN + # check if PSTN GW IP is defined + if (strempty($sel(cfg_get.pstn.gw_ip))) { + xlog("SCRIPT: PSTN routing enabled but pstn.gw_ip not defined\n"); + return; + } + + # route to PSTN dialed numbers starting with '+' or '00' + # (international format) + # - update the condition to match your dialing rules for PSTN routing + if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$")) return; + + # only local users allowed to call + if(from_uri!=myself) { + sl_send_reply("403", "Not Allowed"); + exit; + } + + # normalize target number for pstn gateway + # - convert leading 00 to + + if (starts_with("$rU", "00")) { + strip(2); + prefix("+"); + } + + if (strempty($sel(cfg_get.pstn.gw_port))) { + $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip); + } else { + $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip) + ":" + + $sel(cfg_get.pstn.gw_port); + } + + route(RELAY); + exit; +#!endif + + return; +} + +# JSONRPC over HTTP(S) routing +#!ifdef WITH_JSONRPC +event_route[xhttp:request] { + set_reply_close(); + set_reply_no_connect(); + if(src_ip!=127.0.0.1) { + xhttp_reply("403", "Forbidden", "text/html", + "Not allowed from $si"); + exit; + } + if ($hu =~ "^/RPC") { + jsonrpc_dispatch(); + exit; + } + + xhttp_reply("200", "OK", "text/html", + "Wrong URL $hu"); + exit; +} +#!endif + +# Routing to voicemail server +route[TOVOICEMAIL] { +#!ifdef WITH_VOICEMAIL + if(!is_method("INVITE|SUBSCRIBE")) return; + + # check if VoiceMail server IP is defined + if (strempty($sel(cfg_get.voicemail.srv_ip))) { + xlog("SCRIPT: VoiceMail routing enabled but IP not defined\n"); + return; + } + if(is_method("INVITE")) { + if($avp(oexten)==$null) return; + + $ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip) + + ":" + $sel(cfg_get.voicemail.srv_port); + } else { + if($rU==$null) return; + + $ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip) + + ":" + $sel(cfg_get.voicemail.srv_port); + } + route(RELAY); + exit; +#!endif + + return; +} + +# Manage outgoing branches +branch_route[MANAGE_BRANCH] { + xdbg("new branch [$T_branch_idx] to $ru\n"); + route(NATMANAGE); +} + +# Manage incoming replies +reply_route { + if(!sanity_check("17604", "6")) { + xlog("Malformed SIP response from $si:$sp\n"); + drop; + } +} + +# Manage incoming replies in transaction context +onreply_route[MANAGE_REPLY] { + xdbg("incoming reply\n"); + if(status=~"[12][0-9][0-9]") { + route(NATMANAGE); + } +} + +# Manage failure routing cases +failure_route[MANAGE_FAILURE] { + route(NATMANAGE); + + if (t_is_canceled()) exit; + +#!ifdef WITH_BLOCK3XX + # block call redirect based on 3xx replies. + if (t_check_status("3[0-9][0-9]")) { + t_reply("404","Not found"); + exit; + } +#!endif + +#!ifdef WITH_BLOCK401407 + # block call redirect based on 401, 407 replies. + if (t_check_status("401|407")) { + t_reply("404","Not found"); + exit; + } +#!endif + +#!ifdef WITH_VOICEMAIL + # serial forking + # - route to voicemail on busy or no answer (timeout) + if (t_check_status("486|408")) { + $du = $null; + route(TOVOICEMAIL); + exit; + } +#!endif +} diff --git a/kamailio/kamctlrc b/kamailio/kamctlrc new file mode 100644 index 0000000..56db7f6 --- /dev/null +++ b/kamailio/kamctlrc @@ -0,0 +1,162 @@ +# The Kamailio configuration file for the control tools. +# +# Here you can set variables used in the kamctl and kamdbctl setup +# scripts. Per default all variables here are commented out, the control tools +# will use their internal default values. + +## your SIP domain +SIP_DOMAIN=my-kamailio-lab.local + +## chrooted directory +# $CHROOT_DIR="/path/to/chrooted/directory" + +## database type: MYSQL, PGSQL, ORACLE, DB_BERKELEY, DBTEXT, or SQLITE +# by default none is loaded +# +# If you want to setup a database with kamdbctl, you must at least specify +# this parameter. +DBENGINE=MYSQL + +## database host +DBHOST=db + +## database port +DBPORT=3306 + +## database name (for ORACLE this is TNS name) +DBNAME=kamailio + +# database path used by dbtext, db_berkeley or sqlite +# DB_PATH="/usr/local/etc/kamailio/dbtext" + +## database read/write user +DBRWUSER="kamailio" + +## password for database read/write user +DBRWPW="kamailiorw" + +## database read only user +# DBROUSER="kamailioro" + +## password for database read only user +# DBROPW="kamailioro" + +## database access host (from where is kamctl used) +# DBACCESSHOST=192.168.0.1 + +## database super user (for ORACLE this is 'scheme-creator' user) +DBROOTUSER="root" + +## password for database super user +## - important: this is insecure, targeting the use only for automatic testing +## - known to work for: mysql +DBROOTPW="" + +## database character set (used by MySQL when creating database) +#CHARSET="latin1" + +## user name column +# USERCOL="username" + + +# SQL definitions +# If you change this definitions here, then you must change them +# in db/schema/entities.xml too. +# FIXME + +# FOREVER="2030-05-28 21:32:15" +# DEFAULT_Q="1.0" + + +# Program to calculate a message-digest fingerprint +# MD5="md5sum" + +# awk tool +# AWK="awk" + +# gdb tool +# GDB="gdb" + +# If you use a system with a grep and egrep that is not 100% gnu grep compatible, +# e.g. solaris, install the gnu grep (ggrep) and specify this below. +# +# grep tool +# GREP="grep" + +# egrep tool +# EGREP="egrep" + +# sed tool +# SED="sed" + +# tail tool +# LAST_LINE="tail -n 1" + +# expr tool +# EXPR="expr" + + +# Describe what additional tables to install. Valid values for the variables +# below are yes/no/ask. With ask (default) it will interactively ask the user +# for an answer, while yes/no allow for automated, unassisted installs. +# + +# If to install tables for the modules in the EXTRA_MODULES variable. +# INSTALL_EXTRA_TABLES=ask + +# If to install presence related tables. +# INSTALL_PRESENCE_TABLES=ask + +# If to install uid modules related tables. +# INSTALL_DBUID_TABLES=ask + +# Define what module tables should be installed. +# If you use the postgres database and want to change the installed tables, then you +# must also adjust the STANDARD_TABLES or EXTRA_TABLES variable accordingly in the +# kamdbctl.base script. + +# Kamailio standard modules +# STANDARD_MODULES="standard acc lcr domain group permissions registrar usrloc msilo +# alias_db uri_db speeddial avpops auth_db pdt dialog dispatcher +# dialplan" + +# Kamailio extra modules +# EXTRA_MODULES="imc cpl siptrace domainpolicy carrierroute userblacklist htable purple sca" + + +## type of aliases used: DB - database aliases; UL - usrloc aliases +## - default: none +# ALIASES_TYPE="DB" + +## control engine: RPCFIFO +## - default RPCFIFO +# CTLENGINE="RPCFIFO" + +## path to FIFO file for engine RPCFIFO +# RPCFIFOPATH="/var/run/kamailio/kamailio_rpc_fifo" + +## check ACL names; default on (1); off (0) +# VERIFY_ACL=1 + +## ACL names - if VERIFY_ACL is set, only the ACL names from below list +## are accepted +# ACL_GROUPS="local ld int voicemail free-pstn" + +## check if user exists (used by some commands such as acl); +## - default on (1); off (0) +# VERIFY_USER=1 + +## verbose - debug purposes - default '0' +# VERBOSE=1 + +## do (1) or don't (0) store plaintext passwords +## in the subscriber table - default '1' +# STORE_PLAINTEXT_PW=0 + +## Kamailio START Options +## PID file path - default is: /var/run/kamailio/kamailio.pid +# PID_FILE=/var/run/kamailio/kamailio.pid + +## Extra start options - default is: not set +# example: start Kamailio with 64MB share memory: STARTOPTIONS="-m 64" +# STARTOPTIONS= diff --git a/mount/asterisk/conf/acl.conf b/mount/asterisk/conf/acl.conf new file mode 100644 index 0000000..b052606 --- /dev/null +++ b/mount/asterisk/conf/acl.conf @@ -0,0 +1,80 @@ +; +; Named Access Control Lists (ACLs) +; +; A convenient way to share acl definitions +; +; This configuration file is read on startup +; +; CLI Commands +; ----------------------------------------------------------- +; acl show Show all named ACLs configured +; acl show Show contents of a particular named ACL +; reload acl Reload configuration file +; +; Any configuration that uses ACLs which has been made to be able to use named +; ACLs will specify a named ACL with the 'acl' option in its configuration in +; a similar fashion to the usual 'permit' and 'deny' options. Example: +; acl=my_named_acl +; +; Multiple named ACLs can be applied by either comma separating the arguments or +; just by adding additional ACL lines. Example: +; acl=my_named_acl +; acl=my_named_acl2 +; +; or +; +; acl=my_named_acl,my_named_acl2 +; +; ACLs specified by name are evaluated independently from the ACL specified via +; permit/deny. In order for an address to pass a given ACL, it must pass both +; the ACL specified by permit/deny for a given item as well as any named ACLs +; that were specified. +; +;[example_named_acl1] +;deny=0.0.0.0/0.0.0.0 +;permit=209.16.236.0 +;permit=209.16.236.1 +; +;[example_named_acl2] +;permit=0.0.0.0/0.0.0.0 +;deny=10.24.20.171 +;deny=10.24.20.103 +;deny=209.16.236.1 +; +; example_named_acl1 above shows an example of whitelisting. When whitelisting, the +; named ACLs should follow a deny that blocks everything (like deny=0.0.0.0/0.0.0.0) +; The following example explains how combining the ACLs works: +; +; [example_item_with_acl] +; acl=example_named_acl1 +; acl=example_named_acl2 +; +; Suppose 209.16.236.0 tries to communicate and the ACL for that example is applied to it... +; First, example_named_acl1 is evaluated. The address is allowed by that ACL. +; Next, example_named_acl2 is evaluated. The address isn't blocked by example_named_acl2 +; either, so it passes. +; +; Suppose instead 209.16.236.1 tries to communicate and the same ACL is applied. +; First, example_named_acl1 is evaluated and the address is allowed. +; However, it is blocked by example_named_acl2, so the address is blocked from the combined +; ACL. +; +; Similarly, the permits/denies in specific configurations that make up an ACL definition +; are also treated as a separate ACL for evaluation. So if we change the example above to: +; +; [example_item_with_acl] +; acl=example_named_acl1 +; acl=example_named_acl2 +; deny=209.16.236.0 +; +; Then 209.16.236.0 will be rejected by the non-named component of the combined ACL even +; though it passes the two named components. +; +; +; Named ACLs can use ipv6 addresses just like normal ACLs. +;[ipv6_example_1] +;deny = :: +;permit = ::1/128 +; +;[ipv6_example_2] +;permit = fe80::21d:bad:fad:2323 diff --git a/mount/asterisk/conf/adsi.conf b/mount/asterisk/conf/adsi.conf new file mode 100644 index 0000000..0f36f80 --- /dev/null +++ b/mount/asterisk/conf/adsi.conf @@ -0,0 +1,8 @@ +; +; Sample ADSI Configuration file +; +[intro] +alignment = center +greeting => Welcome to the +greeting => Asterisk +greeting => Open Source PBX diff --git a/mount/asterisk/conf/agents.conf b/mount/asterisk/conf/agents.conf new file mode 100644 index 0000000..0cf0c4c --- /dev/null +++ b/mount/asterisk/conf/agents.conf @@ -0,0 +1,70 @@ +; +; Agent pool configuration +; + +[general] +; The general section of this config is not currently used, but reserved +; for future use. + +;[agent-id] +; Define ackcall to require the agent to give a DTMF acknowledgement +; when the agent receives a call. +; The channel variable AGENTACKCALL overrides on agent login. +; Default is "no". +;ackcall=no +; +; Set what DTMF key sequence the agent should use to acknowledge a call. +; The channel variable AGENTACCEPTDTMF overrides on agent login. +; This option is ignored unless ackcall is enabled. +; Default is "#". +;acceptdtmf=## +; +; Set how many seconds a call for the agent has to wait for the agent to +; acknowledge the call before the agent is automatically logged off. If +; set to zero then the call will wait forever for the agent to acknowledge. +; The channel variable AGENTAUTOLOGOFF overrides on agent login. +; This option is ignored unless ackcall is enabled. +; Default is 0. +;autologoff=15 +; +; Set the minimum amount of time after disconnecting a call before +; the agent can receive a new call in milliseconds. +; The channel variable AGENTWRAPUPTIME overrides on agent login. +; Default is 0. +;wrapuptime=5000 +; +; Set the musiconhold class for the agent. +; Default is "default". +;musiconhold=default +; +; Enable recording calls the agent takes automatically by invoking the +; DTMF automixmon feature when the agent connects to a caller. +; See features.conf.sample for information about the automixmon feature. +; Default is "no". +;recordagentcalls=yes +; +; The sound file played to alert the agent when a call is present. +; Default is "beep". +;custom_beep=beep +; +; A friendly name for the agent used in log messages. +; Default is "". +;fullname=Mark Spencer +; +; -------------------------------------------------- +; +; This section contains example agent definitions: +; +; Define a template called my-agents: +;[my-agents](!) +;autologoff=15 +;ackcall=yes +;acceptdtmf=## +; +; Define agent 1001 using the my-agents template: +;[1001](my-agents) +;fullname=Mark Spencer +; +; Define agent 1002 using the my-agents template: +;[1002](my-agents) +;fullname=Will Meadows diff --git a/mount/asterisk/conf/alarmreceiver.conf b/mount/asterisk/conf/alarmreceiver.conf new file mode 100644 index 0000000..e4815a9 --- /dev/null +++ b/mount/asterisk/conf/alarmreceiver.conf @@ -0,0 +1,91 @@ +; +; alarmreceiver.conf +; +; Sample configuration file for the Asterisk alarm receiver application. +; + + +[general] + +; +; Specify a timestamp format for the metadata section of the event files +; Default is %a %b %d, %Y @ %H:%M:%S %Z + +timestampformat = %a %b %d, %Y @ %H:%M:%S %Z + +; +; Specify a command to execute when the caller hangs up +; +; Default is none +; + +;eventcmd = yourprogram -yourargs ... + +; +; Specify a spool directory for the event files. This setting is required +; if you want the app to be useful. Event files written to the spool +; directory will be of the template event-XXXXXX, where XXXXXX is a random +; and unique alphanumeric string. +; +; Default is none, and the events will be dropped on the floor. +; + +eventspooldir = /tmp + +; +; The alarmreceiver app can either log the events one-at-a-time to individual +; files in the spool directory, or it can store them until the caller +; disconnects and write them all to one file. +; +; The default setting for logindividualevents is no. +; + +logindividualevents = no + +; +; The timeout for receiving the first DTMF digit is adjustable from 1000 msec. +; to 10000 msec. The default is 2000 msec. Note: if you wish to test the +; receiver by entering digits manually, set this to a reasonable time out +; like 10000 milliseconds. + +fdtimeout = 2000 + +; +; The timeout for receiving subsequent DTMF digits is adjustable from +; 110 msec. to 4000 msec. The default is 200 msec. Note: if you wish to test +; the receiver by entering digits manually, set this to a reasonable time out +; like 4000 milliseconds. +; + +sdtimeout = 200 + +; +; Wait for the connection to settle post-answer. Adjustable from 500 msec. to 10000 msec. +; The default is 1250 msec. +; + +answait = 1250 + +; When logging individual events it may be desirable to skip grouping of metadata + +;no_group_meta = yes + +; +; The loudness of the ACK and Kissoff tones is adjustable from 100 to 8192. +; The default is 8192. This shouldn't need to be messed with, but is included +; just in case there are problems with signal levels. +; + +loudness = 8192 + +; +; The db-family setting allows the user to capture statistics on the number of +; calls, and the errors the alarm receiver sees. The default is for no +; db-family name to be defined and the database logging to be turned off. +; + +;db-family = yourfamily: + +; +; End of alarmreceiver.conf +; diff --git a/mount/asterisk/conf/alsa.conf b/mount/asterisk/conf/alsa.conf new file mode 100644 index 0000000..3e61710 --- /dev/null +++ b/mount/asterisk/conf/alsa.conf @@ -0,0 +1,77 @@ +; +; Open Sound System Console Driver Configuration File +; +[general] +; +; Automatically answer incoming calls on the console? Choose yes if +; for example you want to use this as an intercom. +; +autoanswer=yes +; +; Default context (is overridden with @context syntax) +; +context=local +; +; Default extension to call +; +extension=s +; +; Default language +; +;language=en +; +; Default Music on Hold class to use when this channel is placed on hold in +; the case that the music class is not set on the channel with +; Set(CHANNEL(musicclass)=whatever) in the dialplan and the peer channel +; putting this one on hold did not suggest a class to use. +; +;mohinterpret=default +; +; Silence suppression can be enabled when sound is over a certain threshold. +; The value for the threshold should probably be between 500 and 2000 or so, +; but your mileage may vary. Use the echo test to evaluate the best setting. +;silencesuppression = yes +;silencethreshold = 1000 +; +; To set which ALSA device to use, change this parameter +;input_device=hw:0,0 +;output_device=hw:0,0 + +; +; Default mute state (can also be toggled via CLI) +;mute=true + +; +; If enabled, no audio capture device will be opened. This is useful on +; systems where there will be no return audio path, such as overhead pagers. +;noaudiocapture=true + +; ----------------------------- JITTER BUFFER CONFIGURATION -------------------------- +; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of an + ; ALSA channel. Defaults to "no". An enabled jitterbuffer will + ; be used only if the sending side can create and the receiving + ; side can not accept jitter. The ALSA channel can't accept jitter, + ; thus an enabled jitterbuffer on the receive ALSA side will always + ; be used if the sending side can create jitter. + +; jbmaxsize = 200 ; Max length of the jitterbuffer in milliseconds. + +; jbresyncthreshold = 1000 ; Jump in the frame timestamps over which the jitterbuffer is + ; resynchronized. Useful to improve the quality of the voice, with + ; big jumps in/broken timestamps, usually sent from exotic devices + ; and programs. Defaults to 1000. + +; jbimpl = fixed ; Jitterbuffer implementation, used on the receiving side of a SIP + ; channel. Two implementations are currently available - "fixed" + ; (with size always equals to jbmax-size) and "adaptive" (with + ; variable size, actually the new jb of IAX2). Defaults to fixed. + +; jbtargetextra = 40 ; This option only affects the jb when 'jbimpl = adaptive' is set. + ; The option represents the number of milliseconds by which the new + ; jitter buffer will pad its size. the default is 40, so without + ; modification, the new jitter buffer will set its size to the jitter + ; value plus 40 milliseconds. increasing this value may help if your + ; network normally has low jitter, but occasionally has spikes. + +; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". +; ---------------------------------------------------------------------------------- diff --git a/mount/asterisk/conf/amd.conf b/mount/asterisk/conf/amd.conf new file mode 100644 index 0000000..d1764b5 --- /dev/null +++ b/mount/asterisk/conf/amd.conf @@ -0,0 +1,27 @@ +; +; Answering Machine Detection Configuration +; + +[general] +total_analysis_time = 5000 ; Maximum time allowed for the algorithm to decide + ; on whether the audio represents a HUMAN, or a MACHINE +silence_threshold = 256 ; If the average level of noise in a sample does not reach + ; this value, from a scale of 0 to 32767, then we will consider + ; it to be silence. + +; Greeting ; +initial_silence = 2500 ; Maximum silence duration before the greeting. + ; If exceeded, then the result is detection as a MACHINE. +after_greeting_silence = 800 ; Silence after detecting a greeting. + ; If exceeded, then the result is detection as a HUMAN +greeting = 1500 ; Maximum length of a greeting. If exceeded, then the + ; result is detection as a MACHINE. + +; Word detection ; +min_word_length = 100 ; Minimum duration of Voice to considered as a word +maximum_word_length = 5000 ; Maximum duration of a single Voice utterance allowed. +between_words_silence = 50 ; Minimum duration of silence after a word to consider + ; the audio what follows as a new word + +maximum_number_of_words = 2 ; Maximum number of words in the greeting + ; If exceeded, then the result is detection as a MACHINE diff --git a/mount/asterisk/conf/app_mysql.conf b/mount/asterisk/conf/app_mysql.conf new file mode 100644 index 0000000..fafd4f7 --- /dev/null +++ b/mount/asterisk/conf/app_mysql.conf @@ -0,0 +1,24 @@ +; Configuration file for the MYSQL app addon + +[general] +; +; Nullvalue governs how NULL values are returned from the database. In +; previous versions, the special NULL value was returned as the "NULL" +; string. We now provide an option for the behavior, configured globally. +; nullstring - the string "NULL" +; emptystring - the string "" +; null - unset the variable +; +; WARNING: setting nullvalue=null may have undesireable consequences, in +; particular if you use subroutines in AEL or the LOCAL() variable construct. +; You have been warned. Don't complain if you use that setting in combination +; with Gosub or AEL and get buggy behavior. +; +nullvalue = nullstring + +; If set, autoclear will destroy allocated statement and connection resources +; when the channel ends. For most usage of the MYSQL app, this is what you +; want, but it's conceivable that somebody is sharing MYSQL connections across +; multiple channels, in which case, this should be set to 'no'. Defaults to +; 'no', as this was the original behavior. +autoclear=yes diff --git a/mount/asterisk/conf/app_skel.conf b/mount/asterisk/conf/app_skel.conf new file mode 100644 index 0000000..ada8461 --- /dev/null +++ b/mount/asterisk/conf/app_skel.conf @@ -0,0 +1,27 @@ +[general] +games=3 +cheat=no + +[sounds] +prompt=please-enter-your,number,queue-less-than +wrong_guess=vm-pls-try-again +right_guess=auth-thankyou +too_high=high +too_low=low +lose=vm-goodbye + +[easy] +max_number=10 +max_guesses=4 + +[medium] +max_number=100 +max_guesses=6 + +[hard] +max_number=1000 +max_guesses=7 + +[nightmare] +max_number=1000 +max_guesses=1 diff --git a/mount/asterisk/conf/ari.conf b/mount/asterisk/conf/ari.conf new file mode 100644 index 0000000..5ce3166 --- /dev/null +++ b/mount/asterisk/conf/ari.conf @@ -0,0 +1,37 @@ +[general] +enabled = yes ; When set to no, ARI support is disabled. +;pretty = no ; When set to yes, responses from ARI are +; ; formatted to be human readable. +;allowed_origins = ; Comma separated list of allowed origins, for +; ; Cross-Origin Resource Sharing. May be set to * to +; ; allow all origins. +;auth_realm = ; Realm to use for authentication. Defaults to Asterisk +; ; REST Interface. +; +; Default write timeout to set on websockets. This value may need to be adjusted +; for connections where Asterisk must write a substantial amount of data and the +; receiving clients are slow to process the received information. Value is in +; milliseconds; default is 100 ms. +;websocket_write_timeout = 100 +; +; Display certain channel variables every time a channel-oriented +; event is emitted: +; +; Note that this does incur a performance penalty and should be avoided if possible. +; +;channelvars = var1,var2,var3 + +;[username] +;type = user ; Specifies user configuration +;read_only = no ; When set to yes, user is only authorized for +; ; read-only requests. +; +;password = ; Crypted or plaintext password (see password_format). +; +; password_format may be set to plain (the default) or crypt. When set to crypt, +; crypt(3) is used to validate the password. A crypted password can be generated +; using mkpasswd -m sha-512. +; +; When set to plain, the password is in plaintext. +; +;password_format = plain diff --git a/mount/asterisk/conf/ast_debug_tools.conf b/mount/asterisk/conf/ast_debug_tools.conf new file mode 100644 index 0000000..0f90f85 --- /dev/null +++ b/mount/asterisk/conf/ast_debug_tools.conf @@ -0,0 +1,63 @@ +# +# This file is used by the Asterisk debug tools. +# Unlike other Asterisk config files, this one is +# "sourced" by bash and must adhere to bash semantics. +# + +# A list of coredumps and/or coredump search patterns. +# Bash extended globs are enabled and any resulting files +# that aren't actually coredumps are silently ignored +# so you can be liberal with the globs. +# +# If your patterns contains spaces be sure to only quote +# the portion of the pattern that DOESN'T contain wildcard +# expressions. If you quote the whole pattern, it won't +# be expanded and the glob characters will be treated as +# literals. +# +# The exclusion of files ending ".txt" is just for +# demonstration purposes as non-coredumps will be ignored +# anyway. +COREDUMPS=(/tmp/core[-._]asterisk!(*.txt) /tmp/core[-._]$(hostname)!(*.txt)) + +# The directory to contain output files and work directories. +# For output from existing core files, the default is the +# directory that the core file is found in. For core files +# produced from a running process, the default is /tmp. +OUTPUTDIR=/tmp + +# Date command for the "running" coredump and tarballs. +# DATEFORMAT will be executed to get the timestamp. +# Don't put quotes around the format string or they'll be +# treated as literal characters. Also be aware of colons +# in the output as you can't upload files with colons in +# the name to Jira. +# +# Unix timestamp +#DATEFORMAT='date +%s.%N' +# +# Unix timestamp on *BSD/MacOS after installing coreutils +#DATEFORMAT='gdate +%s.%N' +# +# Readable GMT +#DATEFORMAT='date -u +%FT%H-%M-%S%z' +# +# Readable Local time +DATEFORMAT='date +%FT%H-%M-%S%z' + +# A list of log files and/or log file search patterns using the +# same syntax as COREDUMPS. +# +LOGFILES=(/var/log/asterisk/messages* /var/log/asterisk/queue* \ + /var/log/asterisk/debug* /var/log/asterisk/security*) + +# ast_loggrabber converts POSIX timestamps to readable format +# using this Python strftime format string. If not specified +# or an empty string, no format covnersion is done. +LOG_DATEFORMAT="%m/%d-%H:%M:%S.%f" + +# The timezone to use when converting POSIX timestamps to +# readable format. It can be specified in "/" +# format or in abbreviation format such as "CST6CDT". If not +# specified, the "local" timezone is used. +# LOG_TIMEZONE= diff --git a/mount/asterisk/conf/asterisk.adsi b/mount/asterisk/conf/asterisk.adsi new file mode 100644 index 0000000..904b33a --- /dev/null +++ b/mount/asterisk/conf/asterisk.adsi @@ -0,0 +1,158 @@ +; +; Asterisk default ADSI script +; +; +; Begin with the preamble requirements +; +DESCRIPTION "Asterisk PBX" ; Name of vendor +VERSION 0x00 ; Version of stuff +;SECURITY "_AST" ; Security code +SECURITY 0X9BDBF7AC ; Security code +FDN 0x0000000F ; Descriptor number + +; +; Flags +; +FLAG "nocallwaiting" + +; +; Predefined strings +; +DISPLAY "titles" IS "** Asterisk PBX **" +DISPLAY "talkingto" IS "Call active." JUSTIFY LEFT +DISPLAY "callname" IS "$Call1p" JUSTIFY LEFT +DISPLAY "callnum" IS "$Call1s" JUSTIFY LEFT +DISPLAY "incoming" IS "Incoming call!" JUSTIFY LEFT +DISPLAY "ringing" IS "Calling... " JUSTIFY LEFT +DISPLAY "callended" IS "Call ended." JUSTIFY LEFT +DISPLAY "missedcall" IS "Missed call." JUSTIFY LEFT +DISPLAY "busy" IS "Busy." JUSTIFY LEFT +DISPLAY "reorder" IS "Reorder." JUSTIFY LEFT +DISPLAY "cwdisabled" IS "Callwait disabled" +DISPLAY "empty" IS "asdf" + +; +; Begin soft key definitions +; +KEY "callfwd" IS "CallFwd" OR "Call Forward" + OFFHOOK + VOICEMODE + WAITDIALTONE + SENDDTMF "*60" + GOTO "offHook" +ENDKEY + +KEY "vmail_OH" IS "VMail" OR "Voicemail" + OFFHOOK + VOICEMODE + WAITDIALTONE + SENDDTMF "8500" +ENDKEY + +KEY "vmail" IS "VMail" OR "Voicemail" + SENDDTMF "8500" +ENDKEY + +KEY "backspace" IS "BackSpc" OR "Backspace" + BACKSPACE +ENDKEY + +KEY "cwdisable" IS "CWDsble" OR "Disable Call Wait" + SENDDTMF "*70" + SETFLAG "nocallwaiting" + SHOWDISPLAY "cwdisabled" AT 4 + TIMERCLEAR + TIMERSTART 1 +ENDKEY + +KEY "cidblock" IS "CIDBlk" OR "Block Callerid" + SENDDTMF "*67" + SETFLAG "nocallwaiting" +ENDKEY + +; +; Begin main subroutine +; + +SUB "main" IS + IFEVENT NEARANSWER THEN + CLEAR + SHOWDISPLAY "titles" AT 1 NOUPDATE + SHOWDISPLAY "talkingto" AT 2 NOUPDATE + SHOWDISPLAY "callname" AT 3 + SHOWDISPLAY "callnum" AT 4 + GOTO "stableCall" + ENDIF + IFEVENT OFFHOOK THEN + CLEAR + CLEARFLAG "nocallwaiting" + CLEARDISPLAY + SHOWDISPLAY "titles" AT 1 + SHOWKEYS "vmail" + SHOWKEYS "cidblock" + SHOWKEYS "cwdisable" UNLESS "nocallwaiting" + GOTO "offHook" + ENDIF + IFEVENT IDLE THEN + CLEAR + SHOWDISPLAY "titles" AT 1 + SHOWKEYS "vmail_OH" + ENDIF + IFEVENT CALLERID THEN + CLEAR +; SHOWDISPLAY "titles" AT 1 NOUPDATE +; SHOWDISPLAY "incoming" AT 2 NOUPDATE + SHOWDISPLAY "callname" AT 3 NOUPDATE + SHOWDISPLAY "callnum" AT 4 + ENDIF + IFEVENT RING THEN + CLEAR + SHOWDISPLAY "titles" AT 1 NOUPDATE + SHOWDISPLAY "incoming" AT 2 + ENDIF + IFEVENT ENDOFRING THEN + SHOWDISPLAY "missedcall" AT 2 + CLEAR + SHOWDISPLAY "titles" AT 1 + SHOWKEYS "vmail_OH" + ENDIF + IFEVENT TIMER THEN + CLEAR + SHOWDISPLAY "empty" AT 4 + ENDIF +ENDSUB + +SUB "offHook" IS + IFEVENT FARRING THEN + CLEAR + SHOWDISPLAY "titles" AT 1 NOUPDATE + SHOWDISPLAY "ringing" AT 2 NOUPDATE + SHOWDISPLAY "callname" at 3 NOUPDATE + SHOWDISPLAY "callnum" at 4 + ENDIF + IFEVENT FARANSWER THEN + CLEAR + SHOWDISPLAY "talkingto" AT 2 + GOTO "stableCall" + ENDIF + IFEVENT BUSY THEN + CLEAR + SHOWDISPLAY "titles" AT 1 NOUPDATE + SHOWDISPLAY "busy" AT 2 NOUPDATE + SHOWDISPLAY "callname" at 3 NOUPDATE + SHOWDISPLAY "callnum" at 4 + ENDIF + IFEVENT REORDER THEN + CLEAR + SHOWDISPLAY "titles" AT 1 NOUPDATE + SHOWDISPLAY "reorder" AT 2 NOUPDATE + SHOWDISPLAY "callname" at 3 NOUPDATE + SHOWDISPLAY "callnum" at 4 + ENDIF +ENDSUB + +SUB "stableCall" IS + IFEVENT REORDER THEN + SHOWDISPLAY "callended" AT 2 + ENDIF +ENDSUB diff --git a/mount/asterisk/conf/asterisk.conf b/mount/asterisk/conf/asterisk.conf new file mode 100644 index 0000000..3c1a403 --- /dev/null +++ b/mount/asterisk/conf/asterisk.conf @@ -0,0 +1,133 @@ +[directories](!) +astetcdir => /etc/asterisk +astmoddir => /usr/lib/asterisk/modules +astvarlibdir => /var/lib/asterisk +astdbdir => /var/lib/asterisk +astkeydir => /var/lib/asterisk +astdatadir => /var/lib/asterisk +astagidir => /var/lib/asterisk/agi-bin +astspooldir => /var/spool/asterisk +astrundir => /var/run/asterisk +astlogdir => /var/log/asterisk +astsbindir => /usr/sbin + +[options] +;verbose = 3 +;debug = 3 +;trace = 0 ; Set the trace level. +;refdebug = yes ; Enable reference count debug logging. +;alwaysfork = yes ; Same as -F at startup. +;nofork = yes ; Same as -f at startup. +;quiet = yes ; Same as -q at startup. +;timestamp = yes ; Same as -T at startup. +;execincludes = yes ; Support #exec in config files. +;console = yes ; Run as console (same as -c at startup). +;highpriority = yes ; Run realtime priority (same as -p at + ; startup). +;initcrypto = yes ; Initialize crypto keys (same as -i at + ; startup). +;nocolor = yes ; Disable console colors. +;dontwarn = yes ; Disable some warnings. +;dumpcore = yes ; Dump core on crash (same as -g at startup). +;languageprefix = yes ; Use the new sound prefix path syntax. +;systemname = my_system_name ; Prefix uniqueid with a system name for + ; Global uniqueness issues. +;autosystemname = yes ; Automatically set systemname to hostname, + ; uses 'localhost' on failure, or systemname if + ; set. +;mindtmfduration = 80 ; Set minimum DTMF duration in ms (default 80 ms) + ; If we get shorter DTMF messages, these will be + ; changed to the minimum duration +;maxcalls = 10 ; Maximum amount of calls allowed. +;maxload = 0.9 ; Asterisk stops accepting new calls if the + ; load average exceed this limit. +;maxfiles = 1000 ; Maximum amount of openfiles. +;minmemfree = 1 ; In MBs, Asterisk stops accepting new calls if + ; the amount of free memory falls below this + ; watermark. +;cache_media_frames = yes ; Cache media frames for performance + ; Disable this option to help track down media frame + ; mismanagement when using valgrind or MALLOC_DEBUG. + ; The cache gets in the way of determining if the + ; frame is used after being freed and who freed it. + ; NOTE: This option has no effect when Asterisk is + ; compiled with the LOW_MEMORY compile time option + ; enabled because the cache code does not exist. + ; Default yes +;cache_record_files = yes ; Cache recorded sound files to another + ; directory during recording. +;record_cache_dir = /tmp ; Specify cache directory (used in conjunction + ; with cache_record_files). +;transmit_silence = yes ; Transmit silence while a channel is in a + ; waiting state, a recording only state, or + ; when DTMF is being generated. Note that the + ; silence internally is generated in raw signed + ; linear format. This means that it must be + ; transcoded into the native format of the + ; channel before it can be sent to the device. + ; It is for this reason that this is optional, + ; as it may result in requiring a temporary + ; codec translation path for a channel that may + ; not otherwise require one. +;transcode_via_sln = yes ; Build transcode paths via SLINEAR, instead of + ; directly. +;runuser = asterisk ; The user to run as. +;rungroup = asterisk ; The group to run as. +;lightbackground = yes ; If your terminal is set for a light-colored + ; background. +;forceblackbackground = yes ; Force the background of the terminal to be + ; black, in order for terminal colors to show + ; up properly. +;defaultlanguage = en ; Default language +documentation_language = en_US ; Set the language you want documentation + ; displayed in. Value is in the same format as + ; locale names. +;hideconnect = yes ; Hide messages displayed when a remote console + ; connects and disconnects. +;lockconfdir = no ; Protect the directory containing the + ; configuration files (/etc/asterisk) with a + ; lock. +;stdexten = gosub ; How to invoke the extensions.conf stdexten. + ; macro - Invoke the stdexten using a macro as + ; done by legacy Asterisk versions. + ; gosub - Invoke the stdexten using a gosub as + ; documented in extensions.conf.sample. + ; Default gosub. +;live_dangerously = no ; Enable the execution of 'dangerous' dialplan + ; functions from external sources (AMI, + ; etc.) These functions (such as SHELL) are + ; considered dangerous because they can allow + ; privilege escalation. + ; Default no +;entityid=00:11:22:33:44:55 ; Entity ID. + ; This is in the form of a MAC address. + ; It should be universally unique. + ; It must be unique between servers communicating + ; with a protocol that uses this value. + ; This is currently is used by DUNDi and + ; Exchanging Device and Mailbox State + ; using protocols: XMPP, Corosync and PJSIP. +;rtp_use_dynamic = yes ; When set to "yes" RTP dynamic payload types + ; are assigned dynamically per RTP instance vs. + ; allowing Asterisk to globally initialize them + ; to pre-designated numbers (defaults to "yes"). +;rtp_pt_dynamic = 35 ; Normally the Dynamic RTP Payload Type numbers + ; are 96-127, which allow just 32 formats. The + ; starting point 35 enables the range 35-63 and + ; allows 29 additional formats. When you use + ; more than 32 formats in the dynamic range and + ; calls are not accepted by a remote + ; implementation, please report this and go + ; back to value 96. +;hide_messaging_ami_events = no; This option, if enabled, will + ; suppress all of the Message/ast_msg_queue channel's + ; housekeeping AMI and ARI channel events. This can + ; reduce the load on the manager and ARI applications + ; when the Digium Phone Module for Asterisk is in use. + +; Changing the following lines may compromise your security. +;[files] +;astctlpermissions = 0660 +;astctlowner = root +;astctlgroup = apache +;astctl = asterisk.ctl diff --git a/mount/asterisk/conf/calendar.conf b/mount/asterisk/conf/calendar.conf new file mode 100644 index 0000000..08cbd3a --- /dev/null +++ b/mount/asterisk/conf/calendar.conf @@ -0,0 +1,111 @@ +;[calendar1] +;type = ical ; type of calendar--currently supported: ical, caldav, exchange, or ews +;url = https://example.com/home/jdoe/Calendar/ ; URL to shared calendar (Zimbra example) +;user = jdoe ; web username +;secret = supersecret ; web password +;refresh = 15 ; refresh calendar every n minutes +;timeframe = 60 ; number of minutes of calendar data to pull for each refresh period +; ; should always be >= refresh +;fetch_again_at_reload = no ; to reload the calendar content when the module is reloaded +; +; +; You can set up res_calendar to execute a call upon an upcoming busy status +; The following fields are available from the ${CALENDAR_EVENT()} dialplan function: +; +; summary : The VEVENT Summary property or Exchange subject +; description : The text description of the vent +; organizer : The organizer of the event +; location : The location field of the event +; calendar : The name of the calendar tied to the event +; uid : The unique ID for this event +; start : Start time of the event +; end : The end time of the event +; busystate : 0=FREE, 1=TENTATIVE, 2=BUSY +; +;autoreminder = 10 ; Override event-defined reminder before each busy status (in mins) +; +;channel = SIP/60001 ; Channel to dial +;context = default ; Context to connect to on answer +;extension = 123 ; Extension to connect to on answer +; +; or +; +;app = Playback ; Application to execute on answer (instead of context/extension) +;appdata = tt-weasels ; Data part of application to execute on answer +; +;waittime = 30 ; How long to wait for an answer, defaults to 30 seconds +; +; Channel variables can be set on the notification channel. The format is +; setvar=name=value. Variable subsitution is done on the value to allow the use of dialplan +; functions like CALENDAR_EVENT. The variables are set in order, so one can use the value +; of earlier variables in the definition of later ones. +; +;setvar = CALLERID(name)=${CALENDAR_EVENT(summary)} + +;[calendar2] +; Note: Support for Exchange Server 2003 +; +;type = exchange ; type of calendar--currently supported: ical, caldav, exchange, or ews +;url = https://example.com/exchange/jdoe ; URL to MS Exchange OWA for user (usually includes exchange/user) +;user = jdoe ; Exchange username +;secret = mysecret ; Exchange password +;refresh = 15 ; refresh calendar every n minutes +;timeframe = 60 ; number of minutes of calendar data to pull for each refresh period +; ; should always be >= refresh +; +; You can set up res_calendar to execute a call upon an upcoming busy status +;autoreminder = 10 ; Override event-defined reminder before each busy status (in mins) +; +;channel = SIP/1234 ; Channel to dial +;context = default ; Context to connect to on answer +;extension = 1234 ; Extension to connect to on answer +; +; or +; +;[calendar3] +; Note: Support for Exchange Server 2007+ +; +;type = ews ; type of calendar--currently supported: ical, caldav, exchange, or ews +;url = https://example.com/ews/Exchange.asmx ; URL to MS Exchange EWS +;user = jdoe ; Exchange username +;secret = mysecret ; Exchange password +;refresh = 15 ; refresh calendar every n minutes +;timeframe = 60 ; number of minutes of calendar data to pull for each refresh period +; ; should always be >= refresh +; +; You can set up res_calendar to execute a call upon an upcoming busy status +;autoreminder = 10 ; Override event-defined reminder before each busy status (in mins) +; +;channel = SIP/1234 ; Channel to dial +;context = default ; Context to connect to on answer +;extension = 1234 ; Extension to connect to on answer +; +; or +; +;app = Playback ; Application to execute on answer (instead of context/extension) +;appdata = tt-weasels ; Data part of application to execute on answer +; +;waittime = 30 ; How long to wait for an answer, defaults to 30 seconds + +;[calendar4] +;type = caldav ; type of calendar--currently supported: ical, caldav, exchange, or ews +;url = https://www.google.com/calendar/dav/username@gmail.com/events/ ; Main GMail calendar (the trailing slash is significant!) +;user = jdoe@gmail.com ; username +;secret = mysecret ; password +;refresh = 15 ; refresh calendar every n minutes +;timeframe = 60 ; number of minutes of calendar data to pull for each refresh period +; ; should always be >= refresh +; +; You can set up res_calendar to execute a call upon an upcoming busy status +;autoreminder = 10 ; Override event-defined reminder before each busy status (in mins) +; +;channel = SIP/1234 ; Channel to dial +;context = default ; Context to connect to on answer +;extension = 1234 ; Extension to connect to on answer +; +; or +; +;app = Playback ; Application to execute on answer (instead of context/extension) +;appdata = tt-weasels ; Data part of application to execute on answer +; +;waittime = 30 ; How long to wait for an answer, defaults to 30 seconds diff --git a/mount/asterisk/conf/ccss.conf b/mount/asterisk/conf/ccss.conf new file mode 100644 index 0000000..7b3fe7d --- /dev/null +++ b/mount/asterisk/conf/ccss.conf @@ -0,0 +1,205 @@ +; +; --- Call Completion Supplementary Services --- +; +; For more information about CCSS, see the CCSS user documentation +; https://wiki.asterisk.org/wiki/display/AST/Call+Completion+Supplementary+Services+(CCSS) +; + +[general] +; The cc_max_requests option is a global limit on the number of +; CC requests that may be in the Asterisk system at any time. +; +;cc_max_requests = 20 +; +; The cc_STATE_devstate variables listed below can be used to change the +; default mapping of the internal state machine tracking the state of +; call completion to an Asterisk Device State value. The acceptable values +; that can be provided are as follows, with a description of what the +; equivalent device BLF that this maps to: +; +; UNKNOWN ; Device is valid but channel didn't know state +; NOT_INUSE ; Device is not used +; INUSE ; Device is in use +; BUSY ; Device is busy +; INVALID ; Device is invalid +; UNAVAILABLE ; Device is unavailable +; RINGING ; Device is ringing +; RINGINUSE ; Device is ringing *and* in use +; ONHOLD ; Device is on hold +; +; These states are used to generate DEVICE_STATE information that can be +; included with Asterisk hints for phones to subscribe to the state information +; or dialplan to check the state using the EXTENSION_STATE() function or +; the DEVICE_STATE() function. +; +; The states are in the format of: "ccss:TECH/ID" so an example of device +; SIP/3000 making a CallCompletionRequest() could be checked by looking at +; DEVICE_STATE(ccss:SIP/3000) or an Asterisk Hint could be generated such as +; +; [hint-context] +; exten => *843000,hint,ccss:SIP/3000 +; +; and then accessed with EXTENSION_STATE(*843000@hint-context) +; or subscribed to with a BLF button on a phone. +; +; The available state mapping and default values are: +; +; cc_available_devstate = NOT_INUSE +; cc_offered_devstate = NOT_INUSE +; cc_caller_requested_devstate = NOT_INUSE +; cc_active_devstate = INUSE +; cc_callee_ready_devstate = INUSE +; cc_caller_busy_devstate = ONHOLD +; cc_recalling_devstate = RINGING +; cc_complete_devstate = NOT_INUSE +; cc_failed_devstate = NOT_INUSE + +; +;============================================ +; PLEASE READ THIS!!! +; The options described below should NOT be +; set in this file. Rather, they should be +; set per-device in a channel driver +; configuration file. +; PLEASE READ THIS!!! +;=========================================== +; +; -------------------------------------------------------------------- +; Timers +; -------------------------------------------------------------------- +;There are three configurable timers for all types of CC: the +;cc_offer_timer, the ccbs_available_timer, and the ccnr_available_timer. +;In addition, when using a generic agent, there is a fourth timer, +;the cc_recall_timer. All timers are configured in seconds, and the +;values shown below are the defaults. +; +;When a caller is offered CCBS or CCNR, the cc_offer_timer will +;be started. If the caller does not request CC before the +;cc_offer_timer expires, then the caller will be unable to request +;CC for this call. +; +;cc_offer_timer = 20 +; +;Once a caller has requested CC, then either the ccbs_available_timer +;or the ccnr_available_timer will run, depending on the service +;requested. The reason why there are two separate timers for CCBS +;and CCNR is that it is reasonable to want to have a shorter timeout +;configured for CCBS than for CCNR. If the available timer expires +;before the called party becomes available, then the CC attempt +;will have failed and monitoring of the called party will stop. +; +;ccbs_available_timer = 4800 +;ccnr_available_timer = 7200 +; +; When using a generic agent, the original caller is called back +; when one of the original called parties becomes available. The +; cc_recall_timer tells Asterisk how long it should let the original +; caller's phone ring before giving up. Please note that this parameter +; only affects operation when using a generic agent. +; +;cc_recall_timer = 20 +; -------------------------------------------------------------------- +; Policies +; -------------------------------------------------------------------- +; Policy settings tell Asterisk how to behave and what sort of +; resources to allocate in order to facilitate CC. There are two +; settings to control the actions Asterisk will take. +; +; The cc_agent_policy describes the behavior that Asterisk will +; take when communicating with the caller during CC. There are +; three possible options. +; +;never: Never offer CC to the caller. Setting the cc_agent_policy +; to this value is the way to disable CC for a call. +; +;generic: A generic CC agent is one which uses no protocol-specific +; mechanisms to offer CC to the caller. Instead, the caller +; requests CC using a dialplan function. Due to internal +; restrictions, you should only use a generic CC agent on +; phones (i.e. not "trunks"). If you are using phones which +; do not support a protocol-specific method of using CC, then +; generic CC agents are what you should use. +; +;native: A native CC agent is one which uses protocol-specific +; signaling to offer CC to the caller and accept CC requests +; from the caller. The supported protocols for native CC +; agents are SIP, ISDN ETSI PTP, ISDN ETSI PTMP, and Q.SIG +;cc_agent_policy=never +; +; The cc_monitor_policy describes the behavior that Asterisk will +; take when communicating with the called party during CC. There +; are four possible options. +; +;never: Analogous to the cc_agent_policy setting. We will never +; attempt to request CC services on this interface. +; +;generic: Analogous to the cc_agent_policy setting. We will monitor +; the called party's progress using protocol-agnostic +; capabilities. Like with generic CC agents, generic CC +; monitors should only be used for phones. +; +;native: Analogous to the cc_agent_policy setting. We will use +; protocol-specific methods to request CC from this interface +; and to monitor the interface for availability. +; +;always: If an interface is set to "always," then we will accept +; protocol-specific CC offers from the caller and use +; a native CC monitor for the remainder of the CC transaction. +; However, if the interface does not offer protocol-specific +; CC, then we will fall back to using a generic CC monitor +; instead. This is a good setting to use for phones for which +; you do not know if they support protocol-specific CC +; methodologies. +;cc_monitor_policy=never +; +; +; -------------------------------------------------------------------- +; Limits +; -------------------------------------------------------------------- +; +; The use of CC requires Asterisk to potentially use more memory than +; some administrators would like. As such, it is a good idea to limit +; the number of CC requests that can be in the system at a given time. +; The values shown below are the defaults. +; +; The cc_max_agents setting limits the number of outstanding CC +; requests a caller may have at any given time. Please note that due +; to implementation restrictions, this setting is ignored when using +; generic CC agents. Generic CC agents may only have one outstanding +; CC request. +; +;cc_max_agents = 5 +; +; The cc_max_monitors setting limits the number of outstanding CC +; requests can be made to a specific interface at a given time. +; +;cc_max_monitors = 5 +; +; -------------------------------------------------------------------- +; Other +; -------------------------------------------------------------------- +; +; When using a generic CC agent, the caller who requested CC will be +; called back when a called party becomes available. When the caller +; answers his phone, the administrator may opt to have a macro run. +; What this macro does is up to the administrator. By default there +; is no callback macro configured. +; +;cc_callback_macro= +; +; Alternatively, the administrator may run a subroutine. By default +; there is no callback subroutine configured. The subroutine should +; be specified in the format: [[context,]exten,]priority +; +;cc_callback_sub= +; +; When using an ISDN phone and a generic CC agent, Asterisk is unable +; to determine the dialstring that should be used when calling back +; the original caller. Furthermore, if you desire to use any dialstring- +; specific options, such as distinctive ring, you must set this +; configuration option. For non-ISDN phones, it is not necessary to +; set this, since Asterisk can determine the dialstring to use since +; it is identical to the name of the calling device. By default, there +; is no cc_agent_dialstring set. +; +;cc_agent_dialstring= diff --git a/mount/asterisk/conf/cdr.conf b/mount/asterisk/conf/cdr.conf new file mode 100644 index 0000000..1d0af78 --- /dev/null +++ b/mount/asterisk/conf/cdr.conf @@ -0,0 +1,166 @@ +; +; Asterisk Call Detail Record engine configuration +; +; CDR is Call Detail Record, which provides logging services via a variety of +; pluggable backend modules. Detailed call information can be recorded to +; databases, files, etc. Useful for billing, fraud prevention, compliance with +; Sarbanes-Oxley aka The Enron Act, QOS evaluations, and more. +; + +[general] + +; Define whether or not to use CDR logging. Setting this to "no" will override +; any loading of backend CDR modules. Default is "yes". +;enable=yes + +; Define whether or not to log unanswered calls that don't involve an outgoing +; party. Setting this to "yes" will make calls to extensions that don't answer +; and don't set a B side channel (such as by using the Dial application) +; receive CDR log entries. If this option is set to "no", then those log +; entries will not be created. Unanswered Calls which get offered to an +; outgoing line will always receive log entries regardless of this option, and +; that is the intended behaviour. +;unanswered = no + +; Define whether or not to log congested calls. Setting this to "yes" will +; report each call that fails to complete due to congestion conditions. Default +; is "no". +;congestion = no + +; Normally, CDR's are not closed out until after all extensions are finished +; executing. By enabling this option, the CDR will be ended before executing +; the "h" extension and hangup handlers so that CDR values such as "end" and +; "billsec" may be retrieved inside of of this extension. +; The default value is "no". +;endbeforehexten=no + +; Normally, the 'billsec' field logged to the backends (text files or databases) +; is simply the end time (hangup time) minus the answer time in seconds. Internally, +; asterisk stores the time in terms of microseconds and seconds. By setting +; initiatedseconds to 'yes', you can force asterisk to report any seconds +; that were initiated (a sort of round up method). Technically, this is +; when the microsecond part of the end time is greater than the microsecond +; part of the answer time, then the billsec time is incremented one second. +; The default value is "no". +;initiatedseconds=no + +; Define the CDR batch mode, where instead of posting the CDR at the end of +; every call, the data will be stored in a buffer to help alleviate load on the +; asterisk server. Default is "no". +; +; WARNING WARNING WARNING +; Use of batch mode may result in data loss after unsafe asterisk termination +; ie. software crash, power failure, kill -9, etc. +; WARNING WARNING WARNING +; +;batch=no + +; Define the maximum number of CDRs to accumulate in the buffer before posting +; them to the backend engines. 'batch' must be set to 'yes'. Default is 100. +;size=100 + +; Define the maximum time to accumulate CDRs in the buffer before posting them +; to the backend engines. If this time limit is reached, then it will post the +; records, regardless of the value defined for 'size'. 'batch' must be set to +; 'yes'. Note that time is in seconds. Default is 300 (5 minutes). +;time=300 + +; The CDR engine uses the internal asterisk scheduler to determine when to post +; records. Posting can either occur inside the scheduler thread, or a new +; thread can be spawned for the submission of every batch. For small batches, +; it might be acceptable to just use the scheduler thread, so set this to "yes". +; For large batches, say anything over size=10, a new thread is recommended, so +; set this to "no". Default is "no". +;scheduleronly=no + +; When shutting down asterisk, you can block until the CDRs are submitted. If +; you don't, then data will likely be lost. You can always check the size of +; the CDR batch buffer with the CLI "cdr status" command. To enable blocking on +; submission of CDR data during asterisk shutdown, set this to "yes". Default +; is "yes". +;safeshutdown=yes + +; +; +; CHOOSING A CDR "BACKEND" (what kind of output to generate) +; +; To choose a backend, you have to make sure either the right category is +; defined in this file, or that the appropriate config file exists, and has the +; proper definitions in it. If there are any problems, usually, the entry will +; silently ignored, and you get no output. +; +; Also, please note that you can generate CDR records in as many formats as you +; wish. If you configure 5 different CDR formats, then each event will be logged +; in 5 different places! In the example config files, all formats are commented +; out except for the cdr-csv format. +; +; Here are all the possible back ends: +; +; csv, custom, manager, odbc, pgsql, radius, sqlite, tds +; (also, mysql is available via the asterisk-addons, due to licensing +; requirements) +; (please note, also, that other backends can be created, by creating +; a new backend module in the source cdr/ directory!) +; +; Some of the modules required to provide these backends will not build or install +; unless some dependency requirements are met. Examples of this are pgsql, odbc, +; etc. If you are not getting output as you would expect, the first thing to do +; is to run the command "make menuselect", and check what modules are available, +; by looking in the "2. Call Detail Recording" option in the main menu. If your +; backend is marked with XXX, you know that the "configure" command could not find +; the required libraries for that option. +; +; To get CDRs to be logged to the plain-jane /var/log/asterisk/cdr-csv/Master.csv +; file, define the [csv] category in this file. No database necessary. The example +; config files are set up to provide this kind of output by default. +; +; To get custom csv CDR records, make sure the cdr_custom.conf file +; is present, and contains the proper [mappings] section. The advantage to +; using this backend, is that you can define which fields to output, and in +; what order. By default, the example configs are set up to mimic the cdr-csv +; output. If you don't make any changes to the mappings, you are basically generating +; the same thing as cdr-csv, but expending more CPU cycles to do so! +; +; To get manager events generated, make sure the cdr_manager.conf file exists, +; and the [general] section is defined, with the single variable 'enabled = yes'. +; +; For odbc, make sure all the proper libs are installed, that "make menuselect" +; shows that the modules are available, and the cdr_odbc.conf file exists, and +; has a [global] section with the proper variables defined. +; +; For pgsql, make sure all the proper libs are installed, that "make menuselect" +; shows that the modules are available, and the cdr_pgsql.conf file exists, and +; has a [global] section with the proper variables defined. +; +; For logging to radius databases, make sure all the proper libs are installed, that +; "make menuselect" shows that the modules are available, and the [radius] +; category is defined in this file, and in that section, make sure the 'radiuscfg' +; variable is properly pointing to an existing radiusclient.conf file. +; +; For logging to sqlite databases, make sure the 'cdr.db' file exists in the log directory, +; which is usually /var/log/asterisk. Of course, the proper libraries should be available +; during the 'configure' operation. +; +; For tds logging, make sure the proper libraries are available during the 'configure' +; phase, and that cdr_tds.conf exists and is properly set up with a [global] category. +; +; Also, remember, that if you wish to log CDR info to a database, you will have to define +; a specific table in that databse to make things work! See the doc directory for more details +; on how to create this table in each database. +; + +[csv] +usegmtime=yes ; log date/time in GMT. Default is "no" +loguniqueid=yes ; log uniqueid. Default is "no" +loguserfield=yes ; log user field. Default is "no" +accountlogs=yes ; create separate log file for each account code. Default is "yes" +;newcdrcolumns=yes ; Enable logging of post-1.8 CDR columns (peeraccount, linkedid, sequence). + ; Default is "no". + +;[radius] +;usegmtime=yes ; log date/time in GMT +;loguniqueid=yes ; log uniqueid +;loguserfield=yes ; log user field +; Set this to the location of the radiusclient-ng configuration file +; The default is /etc/radiusclient-ng/radiusclient.conf +;radiuscfg => /usr/local/etc/radiusclient-ng/radiusclient.conf diff --git a/mount/asterisk/conf/cdr_adaptive_odbc.conf b/mount/asterisk/conf/cdr_adaptive_odbc.conf new file mode 100644 index 0000000..1585b87 --- /dev/null +++ b/mount/asterisk/conf/cdr_adaptive_odbc.conf @@ -0,0 +1,62 @@ +; The point of this module is to allow you log whatever you like in terms of +; the CDR variables. Do you want to log uniqueid? Then simply ensure that +; your table has that column. If you don't want the column, ensure that it +; does not exist in the table structure. If you'd like to call uniqueid +; something else in your table, simply provide an alias in the configuration +; file that maps the standard CDR field name (uniqueid) to whatever column +; name you like. Perhaps you'd like some extra CDR values logged that aren't +; in the standard repertoire of CDR variables (some that come to mind are +; certain values used for LCR: route, per_minute_cost, and per_minute_price). +; Simply set those CDR variables in your dialplan, i.e. Set(CDR(route)=27), +; ensure that a corresponding column exists in your table, and cdr_adaptive_odbc +; will do the rest. +; +; This configuration defines the connections and tables for which CDRs may +; be populated. Each context specifies a different CDR table to be used. +; +; The columns in the tables should match up word-for-word (case-insensitive) +; to the CDR variables set in the dialplan. The natural advantage to this +; system is that beyond setting up the configuration file to tell you what +; tables to look at, there isn't anything more to do beyond creating the +; columns for the fields that you want, and populating the corresponding +; CDR variables in the dialplan. For the builtin variables only, you may +; create aliases for the real column name. +; +; Please note that after adding columns to the database, it is necessary to +; reload this module to get the new column names and types read. +; +; Warning: if you specify two contexts with exactly the same connection and +; table names, you will get duplicate records in that table. So be careful. +; + +;[first] +;connection=mysql1 +;table=cdr + +;[second] +;connection=mysql1 +;table=extracdr + +;[third] +;connection=sqlserver +;table=AsteriskCDR +;schema=public ; for databases which support schemas +;usegmtime=yes ; defaults to no +;alias src => source +;alias channel => source_channel +;alias dst => dest +;alias dstchannel => dest_channel +; +; Any filter specified MUST match exactly or the CDR will be discarded +;filter accountcode => somename +;filter src => 123 +; Negative filters are also now available +;filter src != 456 +; +; Additionally, we now support setting static values per column. The reason +; for this is to allow different sections to specify different values for +; a certain named column, presumably separated by filters. +;static "Some Special Value" => identifier_code +; +; Add quoted indentifiers for table and columns names. +;quoted_identifiers=" ; Default to null diff --git a/mount/asterisk/conf/cdr_beanstalkd.conf b/mount/asterisk/conf/cdr_beanstalkd.conf new file mode 100644 index 0000000..4f8d531 --- /dev/null +++ b/mount/asterisk/conf/cdr_beanstalkd.conf @@ -0,0 +1,20 @@ +; +; Asterisk Call Management CDR via Beanstalkd job queue +; +; Beanstalkd is a simple job queue server, that is highly versatile and simple to use. +; Beanstalkd includes the capability of using multiple queues at the same time, with priorities. +; +; This module requires that your server has the beanstalk-client library installed. The library +; can be downloaded from - https://github.com/deepfryed/beanstalk-client +; + +[general] +;enabled = yes + +;host = 127.0.0.1 ; Specify the remote IP address of the Beanstalkd server +;port = 11300 ; Specify the remote PORT of the the Beanstalkd server +;tube = asterisk-cdr ; Specify the default CDR job queue to use +;priority = 99 ; Specify the default job priority for the queue. This parameter is useful when building + ; platform with multiple Asterisk servers, that are used for different functions. For example, + ; none billable CDR records can be inserted with a priority of 99, while billable ones be + ; inserted with a priority of 1 diff --git a/mount/asterisk/conf/cdr_custom.conf b/mount/asterisk/conf/cdr_custom.conf new file mode 100644 index 0000000..bec9e33 --- /dev/null +++ b/mount/asterisk/conf/cdr_custom.conf @@ -0,0 +1,14 @@ +; +; Mappings for custom config file +; +; To get your CSV output in a format tailored to your liking, uncomment the +; following lines and look for the output in the cdr-custom directory (usually +; in /var/log/asterisk). Depending on which mapping you uncomment, you may see +; Master.csv, Simple.csv, or both. +; +;[mappings] +;Master.csv => ${CSV_QUOTE(${CDR(clid)})},${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})},${CSV_QUOTE(${CDR(dcontext)})},${CSV_QUOTE(${CDR(channel)})},${CSV_QUOTE(${CDR(dstchannel)})},${CSV_QUOTE(${CDR(lastapp)})},${CSV_QUOTE(${CDR(lastdata)})},${CSV_QUOTE(${CDR(start)})},${CSV_QUOTE(${CDR(answer)})},${CSV_QUOTE(${CDR(end)})},${CSV_QUOTE(${CDR(duration)})},${CSV_QUOTE(${CDR(billsec)})},${CSV_QUOTE(${CDR(disposition)})},${CSV_QUOTE(${CDR(amaflags)})},${CSV_QUOTE(${CDR(accountcode)})},${CSV_QUOTE(${CDR(uniqueid)})},${CSV_QUOTE(${CDR(userfield)})},${CDR(sequence)} +; +; High Resolution Time for billsec and duration fields +;Master.csv => ${CSV_QUOTE(${CDR(clid)})},${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})},${CSV_QUOTE(${CDR(dcontext)})},${CSV_QUOTE(${CDR(channel)})},${CSV_QUOTE(${CDR(dstchannel)})},${CSV_QUOTE(${CDR(lastapp)})},${CSV_QUOTE(${CDR(lastdata)})},${CSV_QUOTE(${CDR(start)})},${CSV_QUOTE(${CDR(answer)})},${CSV_QUOTE(${CDR(end)})},${CSV_QUOTE(${CDR(duration,f)})},${CSV_QUOTE(${CDR(billsec,f)})},${CSV_QUOTE(${CDR(disposition)})},${CSV_QUOTE(${CDR(amaflags)})},${CSV_QUOTE(${CDR(accountcode)})},${CSV_QUOTE(${CDR(uniqueid)})},${CSV_QUOTE(${CDR(userfield)})},${CDR(sequence)} +;Simple.csv => ${CSV_QUOTE(${EPOCH})},${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})} diff --git a/mount/asterisk/conf/cdr_manager.conf b/mount/asterisk/conf/cdr_manager.conf new file mode 100644 index 0000000..aa596b7 --- /dev/null +++ b/mount/asterisk/conf/cdr_manager.conf @@ -0,0 +1,15 @@ +; +; Asterisk Call Management CDR +; +[general] +enabled = no + +; The "mappings" category can be used to define additional "key: value" pairs +; that will be included in the manager event. (after AccountCode, Source, etc). +; +; Each line like "varname => label" will include a "label: ${CDR(varname)}" +; in the generated event where ${CDR(varname)} its replaced with its value +; +;[mappings] +;rate => Rate +;carrier => Carrier diff --git a/mount/asterisk/conf/cdr_mysql.conf b/mount/asterisk/conf/cdr_mysql.conf new file mode 100644 index 0000000..a1f7d38 --- /dev/null +++ b/mount/asterisk/conf/cdr_mysql.conf @@ -0,0 +1,62 @@ +; +; Note - if the database server is hosted on the same machine as the +; asterisk server, you can achieve a local Unix socket connection by +; setting hostname=localhost +; +; port and sock are both optional parameters. If hostname is specified +; and is not "localhost" (you can use address 127.0.0.1 instead), then +; cdr_mysql will attempt to connect to the port specified or use the +; default port. If hostname is not specified or if hostname is +; "localhost", then cdr_mysql will attempt to connect to the socket file +; specified by sock or otherwise use the default socket file. +; +;[global] +;hostname=database.host.name +;dbname=asteriskcdrdb +;table=cdr +;password=password +;user=asteriskcdruser +;port=3306 +;sock=/tmp/mysql.sock +; By default CDRs are logged in the system's time zone +;cdrzone=UTC ; log CDRs with UTC +;usegmtime=yes ;log date/time in GMT. Default is "no" +;cdrzone=America/New_York ; or use a specific time zone +; +; If your system's locale differs from mysql database character set, +; cdr_mysql can damage non-latin characters in CDR variables. Use this +; option to protect your data. +;charset=koi8r +; +; Older versions of cdr_mysql set the calldate field to whenever the +; record was posted, rather than the start date of the call. This flag +; reverts to the old (incorrect) behavior. Note that you'll also need +; to comment out the "start=calldate" alias, below, to use this. +;compat=no +; +; ssl connections (optional) +;ssl_ca= +;ssl_cert= +;ssl_key= +; +; You may also configure the field names used in the CDR table. +; +[columns] +;static "" => +;alias => +alias start => calldate +;alias clid => +;alias src => +;alias dst => +;alias dcontext => +;alias channel => +;alias dstchannel => +;alias lastapp => +;alias lastdata => +;alias duration => +;alias billsec => +;alias disposition => +;alias amaflags => +;alias accountcode => +;alias userfield => +;alias uniqueid => diff --git a/mount/asterisk/conf/cdr_odbc.conf b/mount/asterisk/conf/cdr_odbc.conf new file mode 100644 index 0000000..663ce09 --- /dev/null +++ b/mount/asterisk/conf/cdr_odbc.conf @@ -0,0 +1,12 @@ +; +; cdr_odbc.conf +; + +;[global] +;dsn=MySQL-test +;loguniqueid=yes +;dispositionstring=yes +;table=cdr ;"cdr" is default table name +;usegmtime=no ; set to "yes" to log in GMT +;hrtime=yes ;Enables microsecond accuracy with the billsec and duration fields +;newcdrcolumns=yes ; Enable logging of post-1.8 CDR columns (peeraccount, linkedid, sequence) diff --git a/mount/asterisk/conf/cdr_pgsql.conf b/mount/asterisk/conf/cdr_pgsql.conf new file mode 100644 index 0000000..c5a989f --- /dev/null +++ b/mount/asterisk/conf/cdr_pgsql.conf @@ -0,0 +1,16 @@ +; Sample Asterisk config file for CDR logging to PostgresSQL +; +; Note that you can use TLS connections to your database server. +; This is configured for your PostgreSQL client installation +; on this system (check for pgsessions.conf) + +[global] +;hostname=localhost +;port=5432 +;dbname=asterisk +;password=password +;user=postgres +;appname=asterisk ; Postgres application_name support (optional). Whitespace not allowed. +;table=cdr ;SQL table where CDRs will be inserted +;encoding=LATIN9 ; Encoding of logged characters in Asterisk +;timezone=UTC ; Uncomment if you want datetime fields in UTC/GMT diff --git a/mount/asterisk/conf/cdr_sqlite3_custom.conf b/mount/asterisk/conf/cdr_sqlite3_custom.conf new file mode 100644 index 0000000..4b88d58 --- /dev/null +++ b/mount/asterisk/conf/cdr_sqlite3_custom.conf @@ -0,0 +1,11 @@ +; +; Mappings for custom config file +; +[master] ; currently, only file "master.db" is supported, with only one table at a time. +;table => cdr +;columns => calldate, clid, dcontext, channel, dstchannel, lastapp, lastdata, duration, billsec, disposition, amaflags, accountcode, uniqueid, userfield, test +;values => '${CDR(start)}','${CDR(clid)}','${CDR(dcontext)}','${CDR(channel)}','${CDR(dstchannel)}','${CDR(lastapp)}','${CDR(lastdata)}','${CDR(duration)}','${CDR(billsec)}','${CDR(disposition)}','${CDR(amaflags)}','${CDR(accountcode)}','${CDR(uniqueid)}','${CDR(userfield)}','${CDR(test)}' +;busy_timeout => 1000 + +;Enable High Resolution Times for billsec and duration fields +;values => '${CDR(start)}','${CDR(clid)}','${CDR(dcontext)}','${CDR(channel)}','${CDR(dstchannel)}','${CDR(lastapp)}','${CDR(lastdata)}','${CDR(duration,f)}','${CDR(billsec,f)}','${CDR(disposition)}','${CDR(amaflags)}','${CDR(accountcode)}','${CDR(uniqueid)}','${CDR(userfield)}','${CDR(test)}' diff --git a/mount/asterisk/conf/cdr_syslog.conf b/mount/asterisk/conf/cdr_syslog.conf new file mode 100644 index 0000000..3a619be --- /dev/null +++ b/mount/asterisk/conf/cdr_syslog.conf @@ -0,0 +1,83 @@ +; +; Asterisk Call Detail Records (CDR) - Syslog Backend +; + +; The cdr_syslog module writes CDRs using the facilities provided by syslog. +; +; Not only must you configure cdr_syslog from this file (cdr_syslog.conf) but +; you will also need to make changes to your /etc/syslog.conf before CDRs will +; be written to syslog. +; +; As an example, you can add the following to /etc/syslog.conf: +; +; local4.info /var/log/asterisk-cdr.log +; +; And then instruct syslogd to re-read the configuration file by sending it a +; HUP signal. On Linux this can be done like this: +; +; kill -HUP `cat /var/run/syslogd.pid` +; +; Finally, you will need to uncomment the [cdr-simple] section below, and restart +; Asterisk. When calls are placed, you should start seeing records appear in +; /var/log/asterisk-cdr.log. + +[general] +; Facility +; +; The 'facility' keyword specifies the syslog facility to use when writing out +; CDRs. +; +; Accepted values: One of the following: +; user, local0, local1, local2, local3, local4, local5, local6 +; and local7. +; +; Note: Depending on your platform, the following may also be +; available: +; auth, authpriv, cron, daemon, ftp, kern, lpr, mail, +; news, syslog, and uucp. +; +; Default value: local4 + +;facility=local0 + +; Priority +; +; Use the 'priority' keyword to select which of the syslog priority levels to +; use when logging CDRs. +; +; Accepted values: One of the following: +; alert, crit, debug, emerg, err, info, notice, warning +; Default value: info + +;priority=warn + +; Note: The settings for 'facility' and 'priority' in the [general] section +; define the default values for all of the logging locations created +; below in separate sections. + +;[cdr-master] +;facility = local5 +;priority = debug + +; Template +; +; The 'template' value allows you to specify a custom format for messages +; written to syslog. This is similar to how cdr_custom is configured. +; +; Allowed values: A diaplan style string. +; Default value: None, this is required field. +; +; Note: Because of the way substitution is done, the only meaningful values +; available when the record is logged are those available via the CDR() +; dialplan function. All other channel variables will be unavailable. + +;template = "${CDR(clid)}","${CDR(src)}","${CDR(dst)}","${CDR(dcontext)}","${CDR(channel)}","${CDR(dstchannel)}","${CDR(lastapp)}","${CDR(lastdata)}","${CDR(start)}","${CDR(answer)}","${CDR(end)}","${CDR(duration)}","${CDR(billsec)}","${CDR(disposition)}","${CDR(amaflags)}","${CDR(accountcode)}","${CDR(uniqueid)}","${CDR(userfield)}" + +; High Resolution Time for billsec and duration fields +;template = "${CDR(clid)}","${CDR(src)}","${CDR(dst)}","${CDR(dcontext)}","${CDR(channel)}","${CDR(dstchannel)}","${CDR(lastapp)}","${CDR(lastdata)}","${CDR(start)}","${CDR(answer)}","${CDR(end)}","${CDR(duration,f)}","${CDR(billsec,f)}","${CDR(disposition)}","${CDR(amaflags)}","${CDR(accountcode)}","${CDR(uniqueid)}","${CDR(userfield)}" +;[cdr-simple] + +; Since we don't specify a facility or priority for this logging location, the +; records will use the defaults specified in the [general] section. + +;template = "We received a call from ${CDR(src)}" diff --git a/mount/asterisk/conf/cdr_tds.conf b/mount/asterisk/conf/cdr_tds.conf new file mode 100644 index 0000000..f3a9d7c --- /dev/null +++ b/mount/asterisk/conf/cdr_tds.conf @@ -0,0 +1,77 @@ +; +; Asterisk Call Detail Records (CDR) - FreeTDS Backend +; + +;[global] + +; Connection +; +; Use the 'connection' keyword to specify one of the instance names from your +; 'freetds.conf' file. Note that 'freetds.conf' is not an Asterisk +; configuration file, but one specific to the FreeTDS library. See the FreeTDS +; documentation on 'freetds.conf' for more information: +; +; http://www.freetds.org/userguide/freetdsconf.htm +; +; Accepted values: One of the connections specified in freetds.conf + +;connection=ConnectionFromFreeTDSConf + +; Database Name +; +; The 'dbname' keyword specifies the database name to use when logging CDRs. +; +; Accepted values: Any valid database name + +;dbname=AsteriskCDRs + +; Database Table Name +; +; The 'table' keyword identifies which database table is used to log CDRs. +; +; Accepted value: Any valid table name +; Default value: If not specified, a table named 'cdr' is assumed + +;table=cdr + +; Credentials +; +; The 'username' and 'password' keywords specify the user credentials that +; Asterisk should use when connecting to the database. +; +; Accepted value: Any valid username and password + +;username=mangUsr +;password= + +; Language +; +; The 'language' keyword changes the language which are used for error and +; information messages returned by SQL Server. Each database and user has their +; own default value, and this default can be overriden here. +; +; Accepted value: Any language installed on the target SQL Server. +; Default value: us_english + +;language=us_english + +; Character Set +; +; The 'charset' setting is used to change the character set used when connecting +; to the database server. Each database and database user has their own +; character set setting, and this default can be overriden here. +; +; Accepted value: Any valid character set available on the target SQL server. +; Default value: iso_1 + +;charset=BIG5 + +; High Resolution Times +; +; The 'hrtime' setting is used to store high resolution (sub second) times for +; billsec and duration fields. +; +; Accepted value: true or false +; Default value: false + +;hrtime=false diff --git a/mount/asterisk/conf/cel.conf b/mount/asterisk/conf/cel.conf new file mode 100644 index 0000000..755fcd3 --- /dev/null +++ b/mount/asterisk/conf/cel.conf @@ -0,0 +1,116 @@ +; +; Asterisk Channel Event Logging (CEL) +; + +; Channel Event Logging is a mechanism to provide fine-grained event information +; that can be used to generate billing information. Such event information can +; be recorded to various backend modules. +; + +[general] + +; CEL Activation +; +; Use the 'enable' keyword to turn CEL on or off. +; +; Accepted values: yes and no +; Default value: no + +;enable=yes + +; Application Tracking +; +; Use the 'apps' keyword to specify the list of applications for which you want +; to receive CEL events. This is a comma separated list of Asterisk dialplan +; applications, such as Dial, Queue, and Park. +; +; Accepted values: A comma separated list of Asterisk dialplan applications +; Default value: none +; +; Note: You may also use 'all' which will result in CEL events being reported +; for all Asterisk applications. This may affect Asterisk's performance +; significantly. + +apps=dial,park + +; Event Tracking +; +; Use the 'events' keyword to specify the list of events which you want to be +; raised when they occur. This is a comma separated list of the values in the +; table below. +; +; Accepted values: A comma separated list of one or more of the following: +; ALL -- Generate entries on all events +; CHAN_START -- The time a channel was created +; CHAN_END -- The time a channel was terminated +; ANSWER -- The time a channel was answered (ie, phone taken off-hook) +; HANGUP -- The time at which a hangup occurred +; BRIDGE_ENTER -- The time a channel was connected into a conference room +; BRIDGE_EXIT -- The time a channel was removed from a conference room +; APP_START -- The time a tracked application was started +; APP_END -- the time a tracked application ended +; PARK_START -- The time a call was parked +; PARK_END -- Unpark event +; BLINDTRANSFER -- When a blind transfer is initiated +; ATTENDEDTRANSFER -- When an attended transfer is initiated +; PICKUP -- This channel picked up the specified channel +; FORWARD -- This channel is being forwarded somewhere else +; LINKEDID_END -- The last channel with the given linkedid is retired +; USER_DEFINED -- Triggered from the dialplan, and has a name given by the +; user +; LOCAL_OPTIMIZE -- A local channel pair is optimizing away. +; +; Default value: none +; (Track no events) + +events=APP_START,CHAN_START,CHAN_END,ANSWER,HANGUP,BRIDGE_ENTER,BRIDGE_EXIT + +; Date Format +; +; Use the 'dateformat' keyword to specify the date format used when CEL events +; are raised. +; +; Accepted values: A strftime format string (see man strftime) +; +; Example: "%F %T" +; -> This gives the date and time in the format "2009-06-23 17:02:35" +; +; If this option is not specified, the default format is "." +; since epoch. The microseconds field will always be 6 digits in length, meaning it +; may have leading zeros. +; +;dateformat = %F %T + +; +; Asterisk Manager Interface (AMI) CEL Backend +; +[manager] + +; AMI Backend Activation +; +; Use the 'enable' keyword to turn CEL logging to the Asterisk Manager Interface +; on or off. +; +; Accepted values: yes and no +; Default value: no +;enabled=yes + +; Use 'show_user_defined' to put "USER_DEFINED" in the EventName header, +; instead of (by default) just putting the user defined event name there. +; When enabled the UserDefType header is added for user defined events to +; provide the user defined event name. +; +;show_user_defined=yes + +; +; RADIUS CEL Backend +; +[radius] +; +; Log date/time in GMT +;usegmtime=yes +; +; Set this to the location of the radiusclient-ng configuration file +; The default is /etc/radiusclient-ng/radiusclient.conf +;radiuscfg => /usr/local/etc/radiusclient-ng/radiusclient.conf +; diff --git a/mount/asterisk/conf/cel_beanstalkd.conf b/mount/asterisk/conf/cel_beanstalkd.conf new file mode 100644 index 0000000..8cd0134 --- /dev/null +++ b/mount/asterisk/conf/cel_beanstalkd.conf @@ -0,0 +1,21 @@ +; +; Beanstalkd Job Queue Server CEL Backend +; +[general] + +; Backend Activation +; +; Use the 'enabled' keyword to turn CEL logging +; on or off. +; +; Accepted values: yes and no +; Default value: no +;enabled = yes + +;host = 127.0.0.1 ; Specify the remote IP address of the Beanstalkd server +;port = 11300 ; Specify the remote PORT of the the Beanstalkd server +;tube = asterisk-cel ; Specify the default CDR job queue to use +;priority = 99 ; Specify the default job priority for the queue. This parameter is useful when building + ; platform with multiple Asterisk servers, that are used for different functions. For example, + ; none billable CDR records can be inserted with a priority of 99, while billable ones be + ; inserted with a priority of 1 diff --git a/mount/asterisk/conf/cel_custom.conf b/mount/asterisk/conf/cel_custom.conf new file mode 100644 index 0000000..126248a --- /dev/null +++ b/mount/asterisk/conf/cel_custom.conf @@ -0,0 +1,35 @@ +; +; Asterisk Channel Event Logging (CEL) - Custom CSV Backend +; + +; This is the configuration file for the customizable CSV backend for CEL +; logging. +; +; In order to create custom CSV logs for CEL, uncomment the template below +; (Master.csv) and start Asterisk. Once CEL events are generated, a file will +; appear in the following location: +; +; /var/log/asterisk/cel-custom/Master.csv +; +; (Note that /var/log/asterisk is the default and may differ on your system) +; +; You can also create more than one template if desired. All logs will appear +; in the cel-custom directory under your Asterisk logs directory. +; + +; +; Within a mapping, use the CALLERID() and CHANNEL() functions to retrieve +; details from the CEL event. There are also a few variables created by this +; module that can be used in a mapping: +; +; eventtype - The name of the CEL event. +; eventtime - The timestamp of the CEL event. +; eventenum - Like eventtype but is "USER_DEFINED" for a user defined event. +; userdeftype - User defined event type name from CELGenUserEvent(). +; eventextra - Extra data included with this CEL event, typically along with +; an event of type USER_DEFINED from CELGenUserEvent(). +; BRIDGEPEER - Bridged peer channel name at the time of the CEL event. +; CHANNEL(peer) could also be used. +; +[mappings] +;Master.csv => ${CSV_QUOTE(${eventtype})},${CSV_QUOTE(${eventtime})},${CSV_QUOTE(${CALLERID(name)})},${CSV_QUOTE(${CALLERID(num)})},${CSV_QUOTE(${CALLERID(ANI)})},${CSV_QUOTE(${CALLERID(RDNIS)})},${CSV_QUOTE(${CALLERID(DNID)})},${CSV_QUOTE(${CHANNEL(exten)})},${CSV_QUOTE(${CHANNEL(context)})},${CSV_QUOTE(${CHANNEL(channame)})},${CSV_QUOTE(${CHANNEL(appname)})},${CSV_QUOTE(${CHANNEL(appdata)})},${CSV_QUOTE(${CHANNEL(amaflags)})},${CSV_QUOTE(${CHANNEL(accountcode)})},${CSV_QUOTE(${CHANNEL(uniqueid)})},${CSV_QUOTE(${CHANNEL(linkedid)})},${CSV_QUOTE(${BRIDGEPEER})},${CSV_QUOTE(${CHANNEL(userfield)})},${CSV_QUOTE(${userdeftype})},${CSV_QUOTE(${eventextra})} diff --git a/mount/asterisk/conf/cel_odbc.conf b/mount/asterisk/conf/cel_odbc.conf new file mode 100644 index 0000000..0c0b83f --- /dev/null +++ b/mount/asterisk/conf/cel_odbc.conf @@ -0,0 +1,108 @@ +; +; Asterisk Channel Event Logging (CEL) - Adaptive ODBC Backend +; + +; General module options category. +[general] +; Use 'show_user_defined' to put "USER_DEFINED" in the eventtype field, +; instead of (by default) just putting the user defined event name there. +; +;show_user_defined=yes + +; This configuration defines the connections and tables for which CEL records +; may be populated. Each context specifies a different CEL table to be used. +; +; The columns in the tables should match up word-for-word (case-insensitive) to +; the CEL variables set in the dialplan. The natural advantage to this system +; is that beyond setting up the configuration file to tell you what tables to +; look at, there isn't anything more to do beyond creating the columns for the +; fields that you want, and populating the corresponding CEL variables in the +; dialplan. +; +; Please note that after adding columns to the database, it is necessary to +; reload this module to get the new column names and types read. +; +; Warning: if you specify two contexts with exactly the same connection and +; table names, you will get duplicate records in that table. So be careful. +; +; CEL FIELDS: +; eventtype +; CHANNEL_START = 1 +; CHANNEL_END = 2 +; HANGUP = 3 +; ANSWER = 4 +; APP_START = 5 +; APP_END = 6 +; BRIDGE_START = 7 +; BRIDGE_END = 8 +; CONF_START = 9 +; CONF_END = 10 +; PARK_START = 11 +; PARK_END = 12 +; BLINDTRANSFER = 13 +; ATTENDEDTRANSFER = 14 +; TRANSFER = 15 +; HOOKFLASH = 16 +; 3WAY_START = 17 +; 3WAY_END = 18 +; CONF_ENTER = 19 +; CONF_EXIT = 20 +; USER_DEFINED = 21 +; LINKEDID_END = 22 +; BRIDGE_UPDATE = 23 +; PICKUP = 24 +; FORWARD = 25 +; eventtime (timeval, includes microseconds) +; userdeftype (set only if eventtype == USER_DEFINED) +; cid_name +; cid_num +; cid_ani +; cid_rdnis +; cid_dnid +; exten +; context +; channame +; appname +; appdata +; accountcode +; peeraccount +; uniqueid +; linkedid +; amaflags (an int) +; userfield +; peer +; extra + +; The point of this module is to allow you log whatever you like in terms of the +; CEL variables. Do you want to log uniqueid? Then simply ensure that your +; table has that column. If you don't want the column, ensure that it does not +; exist in the table structure. If you'd like to call uniqueid something else +; in your table, simply provide an alias in this file that maps the standard CEL +; field name (uniqueid) to whatever column name you like. + +;[first] +;connection=mysql1 +;table=cel + +;[second] +;connection=mysql1 +;table=extracel + +;[third] +;connection=sqlserver +;table=AsteriskCEL +;usegmtime=yes ; defaults to no +;allowleapsecond=no ; allow leap second in SQL column for eventtime, default yes. +;alias src => source +;alias channel => source_channel +;alias dst => dest +;alias dstchannel => dest_channel + +; Any filter specified MUST match exactly or the event will be discarded +;filter accountcode => somename +;filter src => 123 + +; Additionally, we now support setting static values per column. Reason +; for this is to allow different sections to specify different values for +; a certain named column, presumably separated by filters. +;static "Some Special Value" => identifier_code diff --git a/mount/asterisk/conf/cel_pgsql.conf b/mount/asterisk/conf/cel_pgsql.conf new file mode 100644 index 0000000..13fe069 --- /dev/null +++ b/mount/asterisk/conf/cel_pgsql.conf @@ -0,0 +1,73 @@ +; +; Asterisk Channel Event Logging (CEL) - PostgreSQL Backend +; + +; Sample Asterisk config file for CEL logging to PostgreSQL +; +; CEL field names: +; +; eventtype +; CHANNEL_START = 1 +; CHANNEL_END = 2 +; HANGUP = 3 +; ANSWER = 4 +; APP_START = 5 +; APP_END = 6 +; BRIDGE_START = 7 +; BRIDGE_END = 8 +; CONF_START = 9 +; CONF_END = 10 +; PARK_START = 11 +; PARK_END = 12 +; BLINDTRANSFER = 13 +; ATTENDEDTRANSFER = 14 +; TRANSFER = 15 +; HOOKFLASH = 16 +; 3WAY_START = 17 +; 3WAY_END = 18 +; CONF_ENTER = 19 +; CONF_EXIT = 20 +; USER_DEFINED = 21 +; LINKEDID_END = 22 +; BRIDGE_UPDATE = 23 +; PICKUP = 24 +; FORWARD = 25 +; eventtime (timeval, includes microseconds) +; userdeftype (set only if eventtype == USER_DEFINED) +; cid_name +; cid_num +; cid_ani +; cid_rdnis +; cid_dnid +; exten +; context +; channame +; appname +; appdata +; accountcode +; peeraccount +; uniqueid +; linkedid +; amaflags (an int) +; userfield +; peer +; extra + +[global] +; Use 'show_user_defined' to put "USER_DEFINED" in the eventtype field, +; instead of (by default) just putting the user defined event name there. +; +;show_user_defined=yes + +; Log date/time in GMT. The default of this option is 'no'. +;usegmtime=yes + +;hostname=localhost +;port=5432 +;dbname=asterisk +;password=password +;user=postgres +;table=cel ;SQL table where CEL's will be inserted +;schema=public ;Schema where CEL's table is located. Optional parameter. + ;If schema support is present the default value used will be current_schema(). +;appname=asterisk ; Postgres application_name support (optional). Whitespace not allowed. diff --git a/mount/asterisk/conf/cel_sqlite3_custom.conf b/mount/asterisk/conf/cel_sqlite3_custom.conf new file mode 100644 index 0000000..aa908a4 --- /dev/null +++ b/mount/asterisk/conf/cel_sqlite3_custom.conf @@ -0,0 +1,25 @@ +; +; Asterisk Channel Event Logging (CEL) - SQLite 3 Backend +; + +; +; Mappings for sqlite3 config file +; +; Within a mapping, use the CALLERID() and CHANNEL() functions to retrieve +; details from the CEL event. There are also a few variables created by this +; module that can be used in a mapping: +; +; eventtype - The name of the CEL event. +; eventtime - The timestamp of the CEL event. +; eventenum - Like eventtype but is "USER_DEFINED" for a user defined event. +; userdeftype - User defined event type name from CELGenUserEvent(). +; eventextra - Extra data included with this CEL event, typically along with +; an event of type USER_DEFINED from CELGenUserEvent(). +; BRIDGEPEER - Bridged peer channel name at the time of the CEL event. +; CHANNEL(peer) could also be used. +; +;[master] ; currently, only file "master.db" is supported, with only one table at a time. +;table => cel +;columns => eventtype, eventtime, cidname, cidnum, cidani, cidrdnis, ciddnid, context, exten, channame, appname, appdata, amaflags, accountcode, uniqueid, userfield, peer, userdeftype, eventextra +;values => '${eventtype}','${eventtime}','${CALLERID(name)}','${CALLERID(num)}','${CALLERID(ANI)}','${CALLERID(RDNIS)}','${CALLERID(DNID)}','${CHANNEL(context)}','${CHANNEL(exten)}','${CHANNEL(channame)}','${CHANNEL(appname)}','${CHANNEL(appdata)}','${CHANNEL(amaflags)}','${CHANNEL(accountcode)}','${CHANNEL(uniqueid)}','${CHANNEL(userfield)}','${BRIDGEPEER}','${userdeftype}','${eventextra}' +;busy_timeout => 1000 \ No newline at end of file diff --git a/mount/asterisk/conf/cel_tds.conf b/mount/asterisk/conf/cel_tds.conf new file mode 100644 index 0000000..399093b --- /dev/null +++ b/mount/asterisk/conf/cel_tds.conf @@ -0,0 +1,69 @@ +; +; Asterisk Channel Event Logging (CEL) - FreeTDS Backend +; + +;[global] + +; Connection +; +; Use the 'connection' keyword to specify one of the instance names from your +; 'freetds.conf' file. Note that 'freetds.conf' is not an Asterisk +; configuration file, but one specific to the FreeTDS library. See the FreeTDS +; documentation on 'freetds.conf' for more information: +; +; http://www.freetds.org/userguide/freetdsconf.htm +; +; Accepted values: One of the connections specified in freetds.conf + +;connection=ConnectionFromFreeTDSConf + +; Database Name +; +; The 'dbname' keyword specifies the database name to use when logging CEL +; records. +; +; Accepted values: Any valid database name + +;dbname=MalicoHN + +; Database Table Name +; +; The 'table' keyword identifies which database table is used to log CEL +; records. +; +; Accepted value: Any valid table name +; Default value: If not specified, a table named 'cel' is assumed + +;table=cel + +; Credentials +; +; The 'username' and 'password' keywords specify the user credentials that +; Asterisk should use when connecting to the database. +; +; Accepted value: Any valid username and password + +;username=mangUsr +;password= + +; Language +; +; The 'language' keyword changes the language which are used for error and +; information messages returned by SQL Server. Each database and user has their +; own default value, and this default can be overriden here. +; +; Accepted value: Any language installed on the target SQL Server. +; Default value: Server default + +;language=us_english + +; Character Set +; +; The 'charset' setting is used to change the character set used when connecting +; to the database server. Each database and database user has their own +; character set setting, and this default can be overriden here. +; +; Accepted value: Any valid character set available on the target server. +; Default value: Server setting + +;charset=BIG5 diff --git a/mount/asterisk/conf/chan_dahdi.conf b/mount/asterisk/conf/chan_dahdi.conf new file mode 100644 index 0000000..d24c22b --- /dev/null +++ b/mount/asterisk/conf/chan_dahdi.conf @@ -0,0 +1,1717 @@ +; +; DAHDI Telephony Configuration file +; +; You need to restart Asterisk to re-configure the DAHDI channel +; CLI> module reload chan_dahdi.so +; will reload the configuration file, but not all configuration options +; are re-configured during a reload (signalling, as well as PRI and +; SS7-related settings cannot be changed on a reload). +; +; This file documents many configuration variables. Normally unless you know +; what a variable means or that it should be changed, there's no reason to +; un-comment those lines. +; +; Examples below that are commented out (those lines that begin with a ';' but +; no space afterwards) typically show a value that is not the default value, +; but would make sense under certain circumstances. The default values are +; usually sane. Thus you should typically not touch them unless you know what +; they mean or you know you should change them. + +[trunkgroups] +; +; Trunk groups are used for NFAS connections. +; +; Group: Defines a trunk group. +; trunkgroup => ,[,...] +; +; trunkgroup is the numerical trunk group to create +; dchannel is the DAHDI channel which will have the +; d-channel for the trunk. +; backup1 is an optional list of backup d-channels. +; +;trunkgroup => 1,24,48 +;trunkgroup => 1,24 +; +; Spanmap: Associates a span with a trunk group +; spanmap => ,[,] +; +; dahdispan is the DAHDI span number to associate +; trunkgroup is the trunkgroup (specified above) for the mapping +; logicalspan is the logical span number within the trunk group to use. +; if unspecified, no logical span number is used. +; +;spanmap => 1,1,1 +;spanmap => 2,1,2 +;spanmap => 3,1,3 +;spanmap => 4,1,4 + +[channels] +; +; Default language +; +;language=en +; +; Context for incoming calls. Defaults to 'default' +; +context=public +; +; Switchtype: Only used for PRI. +; +; national: National ISDN 2 (default) +; dms100: Nortel DMS100 +; 4ess: AT&T 4ESS +; 5ess: Lucent 5ESS +; euroisdn: EuroISDN (common in Europe) +; ni1: Old National ISDN 1 +; qsig: Q.SIG +; +;switchtype=euroisdn +; +; MSNs for ISDN spans. Asterisk will listen for the listed numbers on +; incoming calls and ignore any calls not listed. +; Here you can give a comma separated list of numbers or dialplan extension +; patterns. An empty list disables MSN matching to allow any incoming call. +; Only set on PTMP CPE side of ISDN span if needed. +; The default is an empty list. +;msn= +; +; Some switches (AT&T especially) require network specific facility IE. +; Supported values are currently 'none', 'sdn', 'megacom', 'tollfreemegacom', 'accunet' +; +; nsf cannot be changed on a reload. +; +;nsf=none +; +;service_message_support=yes +; Enable service message support for channel. Must be set after switchtype. +; +; Dialing options for ISDN (i.e., Dial(DAHDI/g1/exten/options)): +; R Reverse Charge Indication +; Indicate to the called party that the call will be reverse charged. +; K(n) Keypad digits n +; Send out the specified digits as keypad digits. +; +; PRI Dialplan: The ISDN-level Type Of Number (TON) or numbering plan, used for +; the dialed number. Leaving this as 'unknown' (the default) works for most +; cases. In some very unusual circumstances, you may need to set this to +; 'dynamic' or 'redundant'. +; +; unknown: Unknown +; private: Private ISDN +; local: Local ISDN +; national: National ISDN +; international: International ISDN +; dynamic: Dynamically selects the appropriate dialplan using the +; prefix settings. +; redundant: Same as dynamic, except that the underlying number is not +; changed (not common) +; +; pridialplan cannot be changed on reload. +;pridialplan=unknown +; +; PRI Local Dialplan: Only RARELY used for PRI (sets the calling number's +; numbering plan). In North America, the typical use is sending the 10 digit +; callerID number and setting the prilocaldialplan to 'national' (the default). +; Only VERY rarely will you need to change this. +; +; unknown: Unknown +; private: Private ISDN +; local: Local ISDN +; national: National ISDN +; international: International ISDN +; from_channel: Use the CALLERID(ton) value from the channel. +; dynamic: Dynamically selects the appropriate dialplan using the +; prefix settings. +; redundant: Same as dynamic, except that the underlying number is not +; changed (not common) +; +; prilocaldialplan cannot be changed on reload. +;prilocaldialplan=national +; +; PRI Connected Line Dialplan: Sets the connected party number's numbering plan. +; +; unknown: Unknown +; private: Private ISDN +; local: Local ISDN +; national: National ISDN +; international: International ISDN +; from_channel: Use the CONNECTEDLINE(ton) value from the channel. +; dynamic: Dynamically selects the appropriate dialplan using the +; prefix settings. +; redundant: Same as dynamic, except that the underlying number is not +; changed (not common) +; +; pricpndialplan cannot be changed on reload. +;pricpndialplan=from_channel +; +; pridialplan may be also set at dialtime, by prefixing the dialed number with +; one of the following letters: +; U - Unknown +; I - International +; N - National +; L - Local (Net Specific) +; S - Subscriber +; V - Abbreviated +; R - Reserved (should probably never be used but is included for completeness) +; +; Additionally, you may also set the following NPI bits (also by prefixing the +; dialed string with one of the following letters): +; u - Unknown +; e - E.163/E.164 (ISDN/telephony) +; x - X.121 (Data) +; f - F.69 (Telex) +; n - National +; p - Private +; r - Reserved (should probably never be used but is included for completeness) +; +; You may also set the prilocaldialplan in the same way, but by prefixing the +; Caller*ID Number rather than the dialed number. + +; Please note that telcos which require this kind of additional manipulation +; of the TON/NPI are *rare*. Most telco PRIs will work fine simply by +; setting pridialplan to unknown or dynamic. +; +; +; PRI caller ID prefixes based on the given TON/NPI (dialplan) +; This is especially needed for EuroISDN E1-PRIs +; +; None of the prefix settings can be changed on reload. +; +; sample 1 for Germany +;internationalprefix = 00 +;nationalprefix = 0 +;localprefix = 0711 +;privateprefix = 07115678 +;unknownprefix = +; +; sample 2 for Germany +;internationalprefix = + +;nationalprefix = +49 +;localprefix = +49711 +;privateprefix = +497115678 +;unknownprefix = +; +; PRI resetinterval: sets the time in seconds between restart of unused +; B channels; defaults to 'never'. +; +;resetinterval = 3600 +; +; Enable per ISDN span to force a RESTART on a channel that returns a cause +; code of PRI_CAUSE_REQUESTED_CHAN_UNAVAIL(44). If this option is enabled +; and the reason the peer rejected the call with cause 44 was that the +; channel is stuck in an unavailable state on the peer, then this might +; help release the channel. It is worth noting that the next outgoing call +; Asterisk makes will likely try the same channel again. +; +; NOTE: Sending a RESTART in response to a cause 44 is not required +; (nor prohibited) by the standards and is likely a primitive chan_dahdi +; response to call collisions (glare) and buggy peers. However, there +; are telco switches out there that ignore the RESTART and continue to +; send calls to the channel in the restarting state. +; Default no. +; +;force_restart_unavailable_chans=yes +; +; Assume inband audio may be present when a SETUP ACK message is received. +; Q.931 Section 5.1.3 says that in scenarios with overlap dialing, when a +; dialtone is sent from the network side, progress indicator 8 "Inband info +; now available" MAY be sent to the CPE if no digits were received with +; the SETUP. It is thus implied that the ie is mandatory if digits came +; with the SETUP and dialtone is needed. +; This option should be enabled, when the network sends dialtone and you +; want to hear it, but the network doesn't send the progress indicator when +; needed. +; +; NOTE: For Q.SIG setups this option should be enabled when outgoing overlap +; dialing is also enabled because Q.SIG does not send the progress indicator +; with the SETUP ACK. +; Default no. +; +;inband_on_setup_ack=yes +; +; Assume inband audio may be present when a PROCEEDING message is received. +; Q.931 Section 5.1.2 says the network cannot assume that the CPE side has +; attached to the B channel at this time without explicitly sending the +; progress indicator ie informing the CPE side to attach to the B channel +; for audio. However, some non-compliant ISDN switches send a PROCEEDING +; without the progress indicator ie indicating inband audio is available and +; assume that the CPE device has connected the media path for listening to +; ringback and other messages. +; Default no. +; +;inband_on_proceeding=yes +; +; Overlap dialing mode (sending overlap digits) +; Cannot be changed on a reload. +; +; incoming: incoming direction only +; outgoing: outgoing direction only +; no: neither direction +; yes or both: both directions +; +;overlapdial=yes + +; Send/receive ISDN display IE options. The display options are a comma separated +; list of the following options: +; +; block: Do not pass display text data. +; Q.SIG: Default for send/receive. +; ETSI CPE: Default for send. +; name_initial: Use display text in SETUP/CONNECT messages as the party name. +; Default for all other modes. +; name_update: Use display text in other messages (NOTIFY/FACILITY) for COLP name +; update. +; name: Combined name_initial and name_update options. +; text: Pass any unused display text data as an arbitrary display message +; during a call. Sent text goes out in an INFORMATION message. +; +; * Default is an empty string for legacy behavior. +; * The name options are not recommended for Q.SIG since Q.SIG already +; supports names. +; * The send block is the only recommended setting for CPE mode since Q.931 uses +; the display IE only in the network to user direction. +; +; display_send and display_receive cannot be changed on reload. +; +;display_send= +;display_receive= + +; Allow sending an ISDN Malicious Caller ID (MCID) request on this span. +; Default disabled +; +;mcid_send=yes + +; Send ISDN date/time IE in CONNECT message option. Only valid on NT spans. +; +; no: Do not send date/time IE in CONNECT message. +; date: Send date only. +; date_hh Send date and hour. +; date_hhmm Send date, hour, and minute. +; date_hhmmss Send date, hour, minute, and second. +; +; Default is an empty string which lets libpri pick the default +; date/time IE send policy. +; +;datetime_send= + +; Send ISDN conected line information. +; +; block: Do not send any connected line information. +; connect: Send connected line information on initial connect. +; update: Same as connect but also send any updates during a call. +; Updates happen if the call is transferred. (Default) +; +;colp_send=update + +; Allow inband audio (progress) when a call is DISCONNECTed by the far end of a PRI +; +;inbanddisconnect=yes +; +; Allow a held call to be transferred to the active call on disconnect. +; This is useful on BRI PTMP NT lines where an ISDN phone can simulate the +; transfer feature of an analog phone. +; The default is no. +;hold_disconnect_transfer=yes + +; BRI PTMP layer 1 presence. +; You should normally not need to set this option. +; You may need to set this option if your telco brings layer 1 down when +; the line is idle. +; required: Layer 1 presence required for outgoing calls. (default) +; ignore: Ignore alarms from DAHDI about this span. +; (Layer 1 and 2 will be brought back up for an outgoing call.) +; NOTE: You will not be able to detect physical line problems +; until an outgoing call is attempted and fails. +; +;layer1_presence=ignore + +; BRI PTMP layer 2 persistence. +; You should normally not need to set this option. +; You may need to set this option if your telco brings layer 1 down when +; the line is idle. +; : Use libpri default. +; keep_up: Bring layer 2 back up if peer takes it down. +; leave_down: Leave layer 2 down if peer takes it down. (Libpri default) +; (Layer 2 will be brought back up for an outgoing call.) +; +;layer2_persistence=leave_down + +; PRI Out of band indications. +; Enable this to report Busy and Congestion on a PRI using out-of-band +; notification. Inband indication, as used by Asterisk doesn't seem to work +; with all telcos. +; +; outofband: Signal Busy/Congestion out of band with RELEASE/DISCONNECT +; inband: Signal Busy/Congestion using in-band tones (default) +; +; priindication cannot be changed on a reload. +; +;priindication = outofband +; +; If you need to override the existing channels selection routine and force all +; PRI channels to be marked as exclusively selected, set this to yes. +; +; priexclusive cannot be changed on a reload. +; +;priexclusive = yes +; +; +; If you need to use the logical channel mapping with your Q.SIG PRI instead +; of the physical mapping you must use the qsigchannelmapping option. +; +; logical: Use the logical channel mapping +; physical: Use physical channel mapping (default) +; +;qsigchannelmapping=logical +; +; If you wish to ignore remote hold indications (and use MOH that is supplied over +; the B channel) enable this option. +; +;discardremoteholdretrieval=yes +; +; ISDN Timers +; All of the ISDN timers and counters that are used are configurable. Specify +; the timer name, and its value (in ms for timers). +; K: Layer 2 max number of outstanding unacknowledged I frames (default 7) +; N200: Layer 2 max number of retransmissions of a frame (default 3) +; T200: Layer 2 max time before retransmission of a frame (default 1000 ms) +; T203: Layer 2 max time without frames being exchanged (default 10000 ms) +; T305: Wait for DISCONNECT acknowledge (default 30000 ms) +; T308: Wait for RELEASE acknowledge (default 4000 ms) +; T309: Maintain active calls on Layer 2 disconnection (default 6000 ms) +; EuroISDN: 6000 to 12000 ms, according to (N200 + 1) x T200 + 2s +; May vary in other ISDN standards (Q.931 1993 : 90000 ms) +; T313: Wait for CONNECT acknowledge, CPE side only (default 3000 ms) +; +; T-RESPONSE: Maximum time to wait for a typical APDU response. (default 4000 ms) +; This is an implementation timer when the standard does not specify one. +; T-ACTIVATE: Request supervision timeout. (default 10000 ms) +; T-RETENTION: Maximum time to wait for user A to activate call-completion. (default 30000 ms) +; Used by ETSI PTP, ETSI PTMP, and Q.SIG as the cc_offer_timer. +; T-CCBS1: T-STATUS timer equivalent for CC user A status. (default 4000 ms) +; T-CCBS2: Maximum time the CCBS service will be active (default 45 min in ms) +; T-CCBS3: Maximum time to wait for user A to respond to user B availability. (default 20000 ms) +; T-CCBS5: Network B CCBS supervision timeout. (default 60 min in ms) +; T-CCBS6: Network A CCBS supervision timeout. (default 60 min in ms) +; T-CCNR2: Maximum time the CCNR service will be active (default 180 min in ms) +; T-CCNR5: Network B CCNR supervision timeout. (default 195 min in ms) +; T-CCNR6: Network A CCNR supervision timeout. (default 195 min in ms) +; CC-T1: Q.SIG CC request supervision timeout. (default 30000 ms) +; CCBS-T2: Q.SIG CCBS supervision timeout. (default 60 min in ms) +; CCNR-T2: Q.SIG CCNR supervision timeout. (default 195 min in ms) +; CC-T3: Q.SIG CC Maximum time to wait for user A to respond to user B availability. (default 30000 ms) +; +;pritimer => t200,1000 +;pritimer => t313,4000 +; +; CC PTMP recall mode: +; specific - Only the CC original party A can participate in the CC callback +; global - Other compatible endpoints on the PTMP line can be party A in the CC callback +; +; cc_ptmp_recall_mode cannot be changed on a reload. +; +;cc_ptmp_recall_mode = specific +; +; CC Q.SIG Party A (requester) retain signaling link option +; retain Require that the signaling link be retained. +; release Request that the signaling link be released. +; do_not_care The responder is free to choose if the signaling link will be retained. +; +;cc_qsig_signaling_link_req = retain +; +; CC Q.SIG Party B (responder) retain signaling link option +; retain Prefer that the signaling link be retained. +; release Prefer that the signaling link be released. +; +;cc_qsig_signaling_link_rsp = retain +; +; See ccss.conf.sample for more options. The timers described by ccss.conf.sample +; are not used by ISDN for the native protocol since they are defined by the +; standards and set by pritimer above. +; +; To enable transmission of facility-based ISDN supplementary services (such +; as caller name from CPE over facility), enable this option. +; Cannot be changed on a reload. +; +;facilityenable = yes +; + +; This option enables Advice of Charge pass-through between the ISDN PRI and +; Asterisk. This option can be set to any combination of 's', 'd', and 'e' which +; represent the different variants of Advice of Charge, AOC-S, AOC-D, and AOC-E. +; Advice of Charge pass-through is currently only supported for ETSI. Since most +; AOC messages are sent on facility messages, the 'facilityenable' option must +; also be enabled to fully support AOC pass-through. +; +;aoc_enable=s,d,e +; +; When this option is enabled, a hangup initiated by the ISDN PRI side of the +; asterisk channel will result in the channel delaying its hangup in an +; attempt to receive the final AOC-E message from its bridge. The delay +; period is configured as one half the T305 timer length. If the channel +; is not bridged the hangup will occur immediatly without delay. +; +;aoce_delayhangup=yes + +; pritimer cannot be changed on a reload. +; +; Signalling method. The default is "auto". Valid values: +; auto: Use the current value from DAHDI. +; em: E & M +; em_e1: E & M E1 +; em_w: E & M Wink +; featd: Feature Group D (The fake, Adtran style, DTMF) +; featdmf: Feature Group D (The real thing, MF (domestic, US)) +; featdmf_ta: Feature Group D (The real thing, MF (domestic, US)) through +; a Tandem Access point +; featb: Feature Group B (MF (domestic, US)) +; fgccama: Feature Group C-CAMA (DP DNIS, MF ANI) +; fgccamamf: Feature Group C-CAMA MF (MF DNIS, MF ANI) +; fxs_ls: FXS (Loop Start) +; fxs_gs: FXS (Ground Start) +; fxs_ks: FXS (Kewl Start) +; fxo_ls: FXO (Loop Start) +; fxo_gs: FXO (Ground Start) +; fxo_ks: FXO (Kewl Start) +; pri_cpe: PRI signalling, CPE side +; pri_net: PRI signalling, Network side +; bri_cpe: BRI PTP signalling, CPE side +; bri_net: BRI PTP signalling, Network side +; bri_cpe_ptmp: BRI PTMP signalling, CPE side +; bri_net_ptmp: BRI PTMP signalling, Network side +; sf: SF (Inband Tone) Signalling +; sf_w: SF Wink +; sf_featd: SF Feature Group D (The fake, Adtran style, DTMF) +; sf_featdmf: SF Feature Group D (The real thing, MF (domestic, US)) +; sf_featb: SF Feature Group B (MF (domestic, US)) +; e911: E911 (MF) style signalling +; ss7: Signalling System 7 +; mfcr2: MFC/R2 Signalling. To specify the country variant see 'mfcr2_variant' +; +; The following are used for Radio interfaces: +; fxs_rx: Receive audio/COR on an FXS kewlstart interface (FXO at the +; channel bank) +; fxs_tx: Transmit audio/PTT on an FXS loopstart interface (FXO at the +; channel bank) +; fxo_rx: Receive audio/COR on an FXO loopstart interface (FXS at the +; channel bank) +; fxo_tx: Transmit audio/PTT on an FXO groundstart interface (FXS at +; the channel bank) +; em_rx: Receive audio/COR on an E&M interface (1-way) +; em_tx: Transmit audio/PTT on an E&M interface (1-way) +; em_txrx: Receive audio/COR AND Transmit audio/PTT on an E&M interface +; (2-way) +; em_rxtx: Same as em_txrx (for our dyslexic friends) +; sf_rx: Receive audio/COR on an SF interface (1-way) +; sf_tx: Transmit audio/PTT on an SF interface (1-way) +; sf_txrx: Receive audio/COR AND Transmit audio/PTT on an SF interface +; (2-way) +; sf_rxtx: Same as sf_txrx (for our dyslexic friends) +; ss7: Signalling System 7 +; +; signalling of a channel can not be changed on a reload. +; +;signalling=fxo_ls +; +; If you have an outbound signalling format that is different from format +; specified above (but compatible), you can specify outbound signalling format, +; (see below). The 'signalling' format specified will be the inbound signalling +; format. If you only specify 'signalling', then it will be the format for +; both inbound and outbound. +; +; outsignalling can only be one of: +; em, em_e1, em_w, sf, sf_w, sf_featd, sf_featdmf, sf_featb, featd, +; featdmf, featdmf_ta, e911, fgccama, fgccamamf +; +; outsignalling cannot be changed on a reload. +; +;signalling=featdmf +; +;outsignalling=featb +; +; For Feature Group D Tandem access, to set the default CIC and OZZ use these +; parameters (Will not be updated on reload): +; +;defaultozz=0000 +;defaultcic=303 +; +; A variety of timing parameters can be specified as well +; The default values for those are "-1", which is to use the +; compile-time defaults of the DAHDI kernel modules. The timing +; parameters, (with the standard default from DAHDI): +; +; prewink: Pre-wink time (default 50ms) +; preflash: Pre-flash time (default 50ms) +; wink: Wink time (default 150ms) +; flash: Flash time (default 750ms) +; start: Start time (default 1500ms) +; rxwink: Receiver wink time (default 300ms) +; rxflash: Receiver flashtime (default 1250ms) +; debounce: Debounce timing (default 600ms) +; +; None of them will update on a reload. +; +; How long generated tones (DTMF and MF) will be played on the channel +; (in milliseconds). +; +; This is a global, rather than a per-channel setting. It will not be +; updated on a reload. +; +;toneduration=100 +; +; Whether or not to do distinctive ring detection on FXO lines: +; +;usedistinctiveringdetection=yes +; +; enable dring detection after caller ID for those countries like Australia +; where the ring cadence is changed *after* the caller ID spill: +; +;distinctiveringaftercid=yes +; +; Whether or not to use caller ID: +; +usecallerid=yes +; +; Type of caller ID signalling in use +; bell = bell202 as used in US (default) +; v23 = v23 as used in the UK +; v23_jp = v23 as used in Japan +; dtmf = DTMF as used in Denmark, Sweden and Netherlands +; smdi = Use SMDI for caller ID. Requires SMDI to be enabled (usesmdi). +; +;cidsignalling=v23 +; +; What signals the start of caller ID +; ring = a ring signals the start (default) +; polarity = polarity reversal signals the start +; polarity_IN = polarity reversal signals the start, for India, +; for dtmf dialtone detection; using DTMF. +; (see https://wiki.asterisk.org/wiki/display/AST/Caller+ID+in+India) +; dtmf = causes monitor loop to look for dtmf energy on the +; incoming channel to initate cid acquisition +; +;cidstart=polarity +; +; When cidstart=dtmf, the energy level on the line used to trigger dtmf cid +; acquisition. This number is compared to the average over a packet of audio +; of the absolute values of 16 bit signed linear samples. The default is set +; to 256. The choice of 256 is arbitrary. The value you should select should +; be high enough to prevent false detections while low enough to insure that +; no dtmf spills are missed. +; +;dtmfcidlevel=256 +; +; Whether or not to hide outgoing caller ID (Override with *67 or *82) +; (If your dialplan doesn't catch it) +; +;hidecallerid=yes +; +; Enable if you need to hide just the name and not the number for legacy PBX use. +; Only applies to PRI channels. +;hidecalleridname=yes +; +; On UK analog lines, the caller hanging up determines the end of calls. So +; Asterisk hanging up the line may or may not end a call (DAHDI could just as +; easily be re-attaching to a prior incoming call that was not yet hung up). +; This option changes the hangup to wait for a dialtone on the line, before +; marking the line as once again available for use with outgoing calls. +; Specified in milliseconds, not set by default. +;waitfordialtone=1000 +; +; For analog lines, enables Asterisk to use dialtone detection per channel +; if an incoming call was hung up before it was answered. If dialtone is +; detected, the call is hung up. +; no: Disabled. (Default) +; yes: Look for dialtone for 10000 ms after answer. +; : Look for dialtone for the specified number of ms after answer. +; always: Look for dialtone for the entire call. Dialtone may return +; if the far end hangs up first. +; +;dialtone_detect=no +; +; The following option enables receiving MWI on FXO lines. The default +; value is no. +; The mwimonitor can take the following values +; no - No mwimonitoring occurs. (default) +; yes - The same as specifying fsk +; fsk - the FXO line is monitored for MWI FSK spills +; fsk,rpas - the FXO line is monitored for MWI FSK spills preceded +; by a ring pulse alert signal. +; neon - The fxo line is monitored for the presence of NEON pulses +; indicating MWI. +; When detected, an internal Asterisk MWI event is generated so that any other +; part of Asterisk that cares about MWI state changes is notified, just as if +; the state change came from app_voicemail. +; For FSK MWI Spills, the energy level that must be seen before starting the +; MWI detection process can be set with 'mwilevel'. +; +;mwimonitor=no +;mwilevel=512 +; +; This option is used in conjunction with mwimonitor. This will get executed +; when incoming MWI state changes. The script is passed 2 arguments. The +; first is the corresponding configured mailbox, and the second is 1 or 0, +; indicating if there are messages waiting or not. +; Note: app_voicemail mailboxes are in the form of mailbox@context. +; +; /usr/local/bin/dahdinotify.sh 501@mailboxes 1 +; +;mwimonitornotify=/usr/local/bin/dahdinotify.sh +; +; The following keyword 'mwisendtype' enables various VMWI methods on FXS lines (if supported). +; The default is to send FSK only. +; The following options are available; +; 'rpas' Ring Pulse Alert Signal, alerts intelligent phones that a FSK message is about to be sent. +; 'lrev' Line reversed to indicate messages waiting. +; 'hvdc' 90Vdc OnHook DC voltage to indicate messages waiting. +; 'hvac' or 'neon' 90Vac OnHook AC voltage to light Neon bulb. +; 'nofsk' Disables FSK MWI spills from being sent out. +; It is feasible that multiple options can be enabled. +;mwisendtype=rpas,lrev +; +; Whether or not to enable call waiting on internal extensions +; With this set to 'yes', busy extensions will hear the call-waiting +; tone, and can use hook-flash to switch between callers. The Dial() +; app will not return the "BUSY" result for extensions. +; +callwaiting=yes +; +; Configure the number of outstanding call waiting calls for internal ISDN +; endpoints before bouncing the calls as busy. This option is equivalent to +; the callwaiting option for analog ports. +; A call waiting call is a SETUP message with no B channel selected. +; The default is zero to disable call waiting for ISDN endpoints. +;max_call_waiting_calls=0 +; +; Allow incoming ISDN call waiting calls. +; A call waiting call is a SETUP message with no B channel selected. +;allow_call_waiting_calls=no + +; Configure the ISDN span to indicate MWI for the list of mailboxes. +; You can give a comma separated list of up to 8 mailboxes per span. +; An empty list disables MWI. +; +; The default is an empty list. +;mwi_mailboxes=vm-mailbox{,vm-mailbox} +; vm-mailbox = Internal voicemail mailbox identifier. +; Note: app_voicemail mailboxes must be in the form of mailbox@context. +;mwi_mailboxes=501@mailboxes,502@mailboxes + +; Configure the ISDN mailbox number sent over the span for MWI mailboxes. +; The position of the number in the list corresponds to the position in +; mwi_mailboxes. If either position in mwi_mailboxes or mwi_vm_boxes is +; empty then that position is disabled. +; +; The default is an empty list. +;mwi_vm_boxes=mailbox_number{,mailbox_number} +;mwi_vm_boxes=501,502 + +; Configure the ISDN span voicemail controlling numbers for MWI mailboxes. +; What number to call for a user to retrieve voicemail messages. +; +; You can give a comma separated list of numbers. The position of the number +; corresponds to the position in mwi_mailboxes. If a position is empty then +; the last number is reused. +; +; For example: +; mwi_vm_numbers=700,,800,,900 +; is equivalent to: +; mwi_vm_numbers=700,700,800,800,900,900,900,900 +; +; The default is no number. +;mwi_vm_numbers= + +; Whether or not restrict outgoing caller ID (will be sent as ANI only, not +; available for the user) +; Mostly use with FXS ports +; Does nothing. Use hidecallerid instead. +; +;restrictcid=no +; +; Whether or not to use the caller ID presentation from the Asterisk channel +; for outgoing calls. +; See dialplan function CALLERID(pres) for more information. +; Only applies to PRI and SS7 channels. +; +usecallingpres=yes +; +; Some countries (UK) have ring tones with different ring tones (ring-ring), +; which means the caller ID needs to be set later on, and not just after +; the first ring, as per the default (1). +; +;sendcalleridafter = 2 +; +; +; Support caller ID on Call Waiting +; +callwaitingcallerid=yes +; +; Support three-way calling +; +threewaycalling=yes +; +; For FXS ports (either direct analog or over T1/E1): +; Support flash-hook call transfer (requires three way calling) +; Also enables call parking (overrides the 'canpark' parameter) +; +; For digital ports using ISDN PRI protocols: +; Support switch-side transfer (called 2BCT, RLT or other names) +; This setting must be enabled on both ports involved, and the +; 'facilityenable' setting must also be enabled to allow sending +; the transfer to the ISDN switch, since it sent in a FACILITY +; message. +; NOTE: This should be disabled for NT PTMP mode. Phones cannot +; have tromboned calls pushed down to them. +; +transfer=yes +; +; Allow call parking +; ('canpark=no' is overridden by 'transfer=yes') +; +canpark=yes + +; Sets the default parking lot for call parking. +; This is setable per channel. +; Parkinglots are configured in features.conf +; +;parkinglot=plaza + +; +; Support call forward variable +; +cancallforward=yes +; +; Whether or not to support Call Return (*69, if your dialplan doesn't +; catch this first) +; +callreturn=yes +; +; Stutter dialtone support: If voicemail is received in the mailbox then +; taking the phone off hook will cause a stutter dialtone instead of a +; normal one. +; +; Note: app_voicemail mailboxes must be in the form of mailbox@context. +; +;mailbox=1234@context +; +; Enable echo cancellation +; Use either "yes", "no", or a power of two from 32 to 256 if you wish to +; actually set the number of taps of cancellation. +; +; Note that when setting the number of taps, the number 256 does not translate +; to 256 ms of echo cancellation. echocancel=256 means 256 / 8 = 32 ms. +; +; Note that if any of your DAHDI cards have hardware echo cancellers, +; then this setting only turns them on and off; numeric settings will +; be treated as "yes". There are no special settings required for +; hardware echo cancellers; when present and enabled in their kernel +; modules, they take precedence over the software echo canceller compiled +; into DAHDI automatically. +; +; +echocancel=yes +; +; Some DAHDI echo cancellers (software and hardware) support adjustable +; parameters; these parameters can be supplied as additional options to +; the 'echocancel' setting. Note that Asterisk does not attempt to +; validate the parameters or their values, so if you supply an invalid +; parameter you will not know the specific reason it failed without +; checking the kernel message log for the error(s) put there by DAHDI. +; +;echocancel=128,param1=32,param2=0,param3=14 +; +; Generally, it is not necessary (and in fact undesirable) to echo cancel when +; the circuit path is entirely TDM. You may, however, change this behavior +; by enabling the echo canceller during pure TDM bridging below. +; +echocancelwhenbridged=yes +; +; In some cases, the echo canceller doesn't train quickly enough and there +; is echo at the beginning of the call. Enabling echo training will cause +; DAHDI to briefly mute the channel, send an impulse, and use the impulse +; response to pre-train the echo canceller so it can start out with a much +; closer idea of the actual echo. Value may be "yes", "no", or a number of +; milliseconds to delay before training (default = 400) +; +; WARNING: In some cases this option can make echo worse! If you are +; trying to debug an echo problem, it is worth checking to see if your echo +; is better with the option set to yes or no. Use whatever setting gives +; the best results. +; +; Note that these parameters do not apply to hardware echo cancellers. +; +;echotraining=yes +;echotraining=800 +; +; If you are having trouble with DTMF detection, you can relax the DTMF +; detection parameters. Relaxing them may make the DTMF detector more likely +; to have "talkoff" where DTMF is detected when it shouldn't be. +; +;relaxdtmf=yes +; +; Hardware gain settings increase/decrease the analog volume level on a channel. +; The values are in db (decibels) and can be adjusted in 0.1 dB increments. +; A positive number increases the volume level on a channel, and a negavive +; value decreases volume level. +; +; Hardware gain settings are only possible on hardware with analog ports +; because the gain is done on the analog side of the analog/digital conversion. +; +; When hardware gains are disabled, Asterisk will NOT touch the gain setting +; already configured in hardware. +; +; hwrxgain: Hardware receive gain for the channel (into Asterisk). +; Default: disabled +; hwtxgain: Hardware transmit gain for the channel (out of Asterisk). +; Default: disabled +; +;hwrxgain=disabled +;hwtxgain=disabled +;hwrxgain=2.0 +;hwtxgain=3.0 +; +; Software gain settings digitally increase/decrease the volume level on a channel. +; The values are in db (decibels). A positive number increases the volume +; level on a channel, and a negavive value decreases volume level. +; +; Software gains work on the digital side of the analog/digital conversion +; and thus can also work with T1/E1 cards. +; +; rxgain: Software receive gain for the channel (into Asterisk). Default: 0.0 +; txgain: Software transmit gain for the channel (out of Asterisk). +; Default: 0.0 +; +; cid_rxgain: Add this gain to rxgain when Asterisk expects to receive +; a Caller ID stream. +; Default: 5.0 . +; +;rxgain=2.0 +;txgain=3.0 +; +; Dynamic Range Compression: You can also enable dynamic range compression +; on a channel. This will digitally amplify quiet sounds while leaving louder +; sounds untouched. This is useful in situations where a linear gain setting +; would cause clipping. Acceptable values are in the range of 0.0 to around +; 6.0 with higher values causing more compression to be done. +; +; rxdrc: dynamic range compression for the rx channel. Default: 0.0 +; txdrc: dynamic range compression for the tx channel. Default: 0.0 +; +;rxdrc=1.0 +;txdrc=4.0 +; +; Logical groups can be assigned to allow outgoing roll-over. Groups range +; from 0 to 63, and multiple groups can be specified. By default the +; channel is not a member of any group. +; +; Note that an explicit empty value for 'group' is invalid, and will not +; override a previous non-empty one. The same applies to callgroup and +; pickupgroup as well. +; +group=1 +; +; Ring groups (a.k.a. call groups) and pickup groups. If a phone is ringing +; and it is a member of a group which is one of your pickup groups, then +; you can answer it by picking up and dialing *8#. For simple offices, just +; make these both the same. Groups range from 0 to 63. +; +callgroup=1 +pickupgroup=1 +; +; Named ring groups (a.k.a. named call groups) and named pickup groups. +; If a phone is ringing and it is a member of a group which is one of your +; named pickup groups, then you can answer it by picking up and dialing *8#. +; For simple offices, just make these both the same. +; The number of named groups is not limited. +; +;namedcallgroup=engineering,sales,netgroup,protgroup +;namedpickupgroup=sales + +; Channel variables to be set for all calls from this channel +;setvar=CHANNEL=42 +;setvar=ATTENDED_TRANSFER_COMPLETE_SOUND=beep ; This channel variable will + ; cause the given audio file to + ; be played upon completion of + ; an attended transfer to the + ; target of the transfer. + +; +; Specify whether the channel should be answered immediately or if the simple +; switch should provide dialtone, read digits, etc. +; Note: If immediate=yes the dialplan execution will always start at extension +; 's' priority 1 regardless of the dialed number! +; +;immediate=yes +; +; Specify whether flash-hook transfers to 'busy' channels should complete or +; return to the caller performing the transfer (default is yes). +; +;transfertobusy=no + +; Calls will have the party id user tag set to this string value. +; +;cid_tag= + +; With this set, you can automatically append the MSN of a party +; to the cid_tag. An '_' is used to separate the tag from the MSN. +; Applies to ISDN spans. +; Default is no. +; +; Table of what number is appended: +; outgoing incoming +; net dialed caller +; cpe caller dialed +; +;append_msn_to_cid_tag=no + +; caller ID can be set to "asreceived" or a specific number if you want to +; override it. Note that "asreceived" only applies to trunk interfaces. +; fullname sets just the +; +; fullname: sets just the name part. +; cid_number: sets just the number part: +; +;callerid = 123456 +; +;callerid = My Name <2564286000> +; Which can also be written as: +;cid_number = 2564286000 +;fullname = My Name +; +;callerid = asreceived +; +; should we use the caller ID from incoming call on DAHDI transfer? +; +;useincomingcalleridondahditransfer = yes +; +; Add a description for the channel which can be shown through the Asterisk +; console when executing the 'dahdi show channels' command is run. +; +;description=Phone located in lobby +; +; AMA flags affects the recording of Call Detail Records. If specified +; it may be 'default', 'omit', 'billing', or 'documentation'. +; +;amaflags=default +; +; Channels may be associated with an account code to ease +; billing +; +;accountcode=lss0101 +; +; ADSI (Analog Display Services Interface) can be enabled on a per-channel +; basis if you have (or may have) ADSI compatible CPE equipment +; +;adsi=yes +; +; SMDI (Simplified Message Desk Interface) can be enabled on a per-channel +; basis if you would like that channel to behave like an SMDI message desk. +; The SMDI port specified should have already been defined in smdi.conf. The +; default port is /dev/ttyS0. +; +;usesmdi=yes +;smdiport=/dev/ttyS0 +; +; On trunk interfaces (FXS) and E&M interfaces (E&M, Wink, Feature Group D +; etc, it can be useful to perform busy detection either in an effort to +; detect hangup or for detecting busies. This enables listening for +; the beep-beep busy pattern. +; +;busydetect=yes +; +; If busydetect is enabled, it is also possible to specify how many busy tones +; to wait for before hanging up. The default is 3, but it might be +; safer to set to 6 or even 8. Mind that the higher the number, the more +; time that will be needed to hangup a channel, but lowers the probability +; that you will get random hangups. +; +;busycount=6 +; +; If busydetect is enabled, it is also possible to specify the cadence of your +; busy signal. In many countries, it is 500msec on, 500msec off. Without +; busypattern specified, we'll accept any regular sound-silence pattern that +; repeats times as a busy signal. If you specify busypattern, +; then we'll further check the length of the sound (tone) and silence, which +; will further reduce the chance of a false positive. +; +;busypattern=500,500 +; +; NOTE: In make menuselect, you'll find further options to tweak the busy +; detector. If your country has a busy tone with the same length tone and +; silence (as many countries do), consider enabling the +; BUSYDETECT_COMPARE_TONE_AND_SILENCE option. +; +; To further detect which hangup tone your telco provider is sending, it is +; useful to use the dahdi_monitor utility to record the audio that main/dsp.c +; is receiving after the caller hangs up. +; +; For FXS (FXO signalled) ports +; switch the line polarity to signal the connected PBX that an outgoing +; call was answered by the remote party. +; For FXO (FXS signalled) ports +; watch for a polarity reversal to mark when a outgoing call is +; answered by the remote party. +; +;answeronpolarityswitch=yes +; +; For FXS (FXO signalled) ports +; switch the line polarity to signal the connected PBX that the current +; call was "hung up" by the remote party +; For FXO (FXS signalled) ports +; In some countries, a polarity reversal is used to signal the disconnect of a +; phone line. If the hanguponpolarityswitch option is selected, the call will +; be considered "hung up" on a polarity reversal. +; +;hanguponpolarityswitch=yes +; +; polarityonanswerdelay: minimal time period (ms) between the answer +; polarity switch and hangup polarity switch. +; (default: 600ms) +; +; On trunk interfaces (FXS) it can be useful to attempt to follow the progress +; of a call through RINGING, BUSY, and ANSWERING. If turned on, call +; progress attempts to determine answer, busy, and ringing on phone lines. +; This feature is HIGHLY EXPERIMENTAL and can easily detect false answers, +; so don't count on it being very accurate. +; +; Few zones are supported at the time of this writing, but may be selected +; with "progzone". +; +; progzone also affects the pattern used for buzydetect (unless +; busypattern is set explicitly). The possible values are: +; us (default) +; ca (alias for 'us') +; cr (Costa Rica) +; br (Brazil, alias for 'cr') +; uk +; +; This feature can also easily detect false hangups. The symptoms of this is +; being disconnected in the middle of a call for no reason. +; +;callprogress=yes +;progzone=uk +; +; Set the tonezone. Equivalent of the defaultzone settings in +; /etc/dahdi/system.conf. This sets the tone zone by number. +; Note that you'd still need to load tonezones (loadzone in +; /etc/dahdi/system.conf). +; The default is -1: not to set anything. +;tonezone = 0 ; 0 is US +; +; FXO (FXS signalled) devices must have a timeout to determine if there was a +; hangup before the line was answered. This value can be tweaked to shorten +; how long it takes before DAHDI considers a non-ringing line to have hungup. +; +; ringtimeout will not update on a reload. +; +;ringtimeout=8000 +; +; For FXO (FXS signalled) devices, whether to use pulse dial instead of DTMF +; Pulse digits from phones (FXS devices, FXO signalling) are always +; detected. +; +;pulsedial=yes +; +; For fax detection, uncomment one of the following lines. The default is *OFF* +; +;faxdetect=both +;faxdetect=incoming +;faxdetect=outgoing +;faxdetect=no +; +; When 'faxdetect' is enabled, one could use 'faxdetect_timeout' to disable fax +; detection after the specified number of seconds into a call. Be aware that +; outgoing analog channels may consider the channel is answered immediately +; when dialing completes. Analog does not have a reliable method of detecting +; when the far end answers. Zero disables the timeout. +; Default is 0 to disable the timeout. +; +;faxdetect_timeout=30 +; +; When 'faxdetect' is used, one could use 'faxbuffers' to configure the DAHDI +; transmit buffer policy. The default is *OFF*. When this configuration +; option is used, the faxbuffer policy will be used for the life of the call +; after a fax tone is detected. The faxbuffer policy is reverted after the +; call is torn down. The sample below will result in 6 buffers and a full +; buffer policy. +; +;faxbuffers=>6,full +; +; When FXO signalling (FXS device, e.g. analog phone) is used, overlap dialing +; is typically used. Asterisk has several configurable (per-channel) timeouts +; to know how long to wait for the next digit. All the values are in +; milliseconds. +; * firstdigit_timeout: a longer timeout before any digit is dialed. +; By default: 16 seconds. +; * interdigit_timeout: timeout for next digits, if the current number dialed +; does not match a number in the current context. Default: 8 seconds. +; * matchdigit_timeout: timeout for next digits, if the current number dialed +; matches a number in the current context. Default: 3 seconds. +; +;firstdigit_timeout=16000 +;interdigit_timeout=8000 +;matchdigit_timeout=3000 +; +; Configure the default number of DAHDI buffers and the transmit policy to use. +; This can be used to eliminate data drops when scheduling jitter prevents +; Asterisk from writing to a DAHDI channel regularly. Most users will probably +; want "faxbuffers" instead of "buffers". +; +; The policies are: +; immediate - DAHDI will immediately start sending the data to the hardware after +; Asterisk writes to the channel. This is the default mode. It +; introduces the least amount of latency but has an increased chance for +; hardware under runs if Asterisk is not able to keep the DAHDI write +; queue from going empty. +; half - DAHDI will wait until half of the configured buffers are full before +; starting to transmit. This adds latency to the audio but reduces +; the chance of under runs. Essentially, this is like an in-kernel jitter +; buffer. +; full - DAHDI will not start transmitting until all buffers are full. +; Introduces the most amount of latency and is susceptible to over +; runs from the Asterisk process. +; +; The receive policy is never changed. DAHDI will always pass up audio as soon +; as possible. +; +; The default number of buffers is 4 (from jitterbuffers) and the default policy +; is immediate. +; +;buffers=4,immediate +; +; This option specifies what to do when the channel's bridged peer puts the +; ISDN channel on hold. Settable per logical ISDN span. +; moh: Generate music-on-hold to the remote party. +; notify: Send hold notification signaling to the remote party. +; For ETSI PTP and ETSI PTMP NT links. +; (The notify setting deprecates the mohinterpret=passthrough setting.) +; hold: Use HOLD/RETRIEVE signaling to release the B channel while on hold. +; For ETSI PTMP TE links. +; +;moh_signaling=moh +; +; This option specifies a preference for which music on hold class this channel +; should listen to when put on hold if the music class has not been set on the +; channel with Set(CHANNEL(musicclass)=whatever) in the dialplan, and the peer +; channel putting this one on hold did not suggest a music class. +; +; This option may be set globally or on a per-channel basis. +; +;mohinterpret=default +; +; This option specifies which music on hold class to suggest to the peer channel +; when this channel places the peer on hold. This option may be set globally, +; or on a per-channel basis. +; +;mohsuggest=default +; +; PRI channels can have an idle extension and a minunused number. So long as +; at least "minunused" channels are idle, chan_dahdi will try to call "idledial" +; on them, and then dump them into the PBX in the "idleext" extension (which +; is of the form exten@context). When channels are needed the "idle" calls +; are disconnected (so long as there are at least "minidle" calls still +; running, of course) to make more channels available. The primary use of +; this is to create a dynamic service, where idle channels are bundled through +; multilink PPP, thus more efficiently utilizing combined voice/data services +; than conventional fixed mappings/muxings. +; +; Those settings cannot be changed on reload. +; +;idledial=6999 +;idleext=6999@dialout +;minunused=2 +;minidle=1 +; +; +; ignore_failed_channels: Continue even if some channels failed to configure. +; True by default. Disable this if you can guarantee that DAHDI starts before +; Asterisk and want to be sure chan_dahdi will not start with broken +; configuration. +; +;ignore_failed_channels = false +; +; Configure jitter buffers in DAHDI (each one is 20ms, default is 4) +; This is set globally, rather than per-channel. +; +;jitterbuffers=4 +; +; ----------------------------- JITTER BUFFER CONFIGURATION -------------------------- +; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a + ; DAHDI channel. Defaults to "no". An enabled jitterbuffer will + ; be used only if the sending side can create and the receiving + ; side can not accept jitter. The DAHDI channel can't accept jitter, + ; thus an enabled jitterbuffer on the receive DAHDI side will always + ; be used if the sending side can create jitter. + +; jbmaxsize = 200 ; Max length of the jitterbuffer in milliseconds. + +; jbresyncthreshold = 1000 ; Jump in the frame timestamps over which the jitterbuffer is + ; resynchronized. Useful to improve the quality of the voice, with + ; big jumps in/broken timestamps, usually sent from exotic devices + ; and programs. Defaults to 1000. + +; jbimpl = fixed ; Jitterbuffer implementation, used on the receiving side of a DAHDI + ; channel. Two implementations are currently available - "fixed" + ; (with size always equals to jbmax-size) and "adaptive" (with + ; variable size, actually the new jb of IAX2). Defaults to fixed. + +; jbtargetextra = 40 ; This option only affects the jb when 'jbimpl = adaptive' is set. + ; The option represents the number of milliseconds by which the new + ; jitter buffer will pad its size. the default is 40, so without + ; modification, the new jitter buffer will set its size to the jitter + ; value plus 40 milliseconds. increasing this value may help if your + ; network normally has low jitter, but occasionally has spikes. + +; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". +; ---------------------------------------------------------------------------------- +; +; You can define your own custom ring cadences here. You can define up to 8 +; pairs. If the silence is negative, it indicates where the caller ID spill is +; to be placed. Also, if you define any custom cadences, the default cadences +; will be turned off. +; +; This setting is global, rather than per-channel. It will not update on +; a reload. +; +; Syntax is: cadence=ring,silence[,ring,silence[...]] +; +; These are the default cadences: +; +;cadence=125,125,2000,-4000 +;cadence=250,250,500,1000,250,250,500,-4000 +;cadence=125,125,125,125,125,-4000 +;cadence=1000,500,2500,-5000 +; +; Each channel consists of the channel number or range. It inherits the +; parameters that were specified above its declaration. +; +; +;callerid="Green Phone"<(256) 428-6121> +;description=Reception Phone ; add a description for 'dahdi show channels' +;channel => 1 +;callerid="Black Phone"<(256) 428-6122> +;description=Courtesy Phone +;channel => 2 +;callerid="CallerID Phone" <(630) 372-1564> +;description= ; reset the description for following channels +;channel => 3 +;callerid="Pac Tel Phone" <(256) 428-6124> +;channel => 4 +;callerid="Uniden Dead" <(256) 428-6125> +;channel => 5 +;callerid="Cortelco 2500" <(256) 428-6126> +;channel => 6 +;callerid="Main TA 750" <(256) 428-6127> +;channel => 44 +; +; For example, maybe we have some other channels which start out in a +; different context and use E & M signalling instead. +; +;context=remote +;signaling=em +;channel => 15 +;channel => 16 + +;signalling=em_w +; +; All those in group 0 I'll use for outgoing calls +; +; Strip most significant digit (9) before sending +; +;stripmsd=1 +;callerid=asreceived +;group=0 +;signalling=fxs_ls +;channel => 45 + +;signalling=fxo_ls +;group=1 +;callerid="Joe Schmoe" <(256) 428-6131> +;channel => 25 +;callerid="Megan May" <(256) 428-6132> +;channel => 26 +;callerid="Suzy Queue" <(256) 428-6233> +;channel => 27 +;callerid="Larry Moe" <(256) 428-6234> +;channel => 28 +; +; Sample PRI (CPE) config: Specify the switchtype, the signalling as either +; pri_cpe or pri_net for CPE or Network termination, and generally you will +; want to create a single "group" for all channels of the PRI. +; +; switchtype cannot be changed on a reload. +; +; switchtype = national +; signalling = pri_cpe +; group = 2 +; channel => 1-23 + +; Used for distinctive ring support for x100p. +; You can see the dringX patterns is to set any one of the dringXcontext fields +; and they will be printed on the console when an inbound call comes in. +; +; dringXrange is used to change the acceptable ranges for "tone offsets". Defaults to 10. +; Note: a range of 0 is NOT what you might expect - it instead forces it to the default. +; A range of -1 will force it to always match. +; Anything lower than -1 would presumably cause it to never match. +; +;dring1=95,0,0 +;dring1context=internal1 +;dring1range=10 +;dring2=325,95,0 +;dring2context=internal2 +;dring2range=10 +; If no pattern is matched here is where we go. +;context=default +;channel => 1 + +; AMI alarm event reporting +;reportalarms=channels +;Possible values are: +;channels - report each channel alarms (current behavior, default for backward compatibility) +;spans - report an "SpanAlarm" event when the span of any configured channel is alarmed +;all - report channel and span alarms (aggregated behavior) +;none - do not report any alarms. + +; ---------------- Options for use with signalling=ss7 ----------------- +; None of them can be changed by a reload. +; +; Variant of SS7 signalling: +; Options are itu and ansi +;ss7type = itu + +; SS7 Called Nature of Address Indicator +; +; unknown: Unknown +; subscriber: Subscriber +; national: National +; international: International +; dynamic: Dynamically selects the appropriate dialplan +; +;ss7_called_nai=dynamic +; +; SS7 Calling Nature of Address Indicator +; +; unknown: Unknown +; subscriber: Subscriber +; national: National +; international: International +; dynamic: Dynamically selects the appropriate dialplan +; +;ss7_calling_nai=dynamic +; +; +; sample 1 for Germany +;ss7_internationalprefix = 00 +;ss7_nationalprefix = 0 +;ss7_subscriberprefix = +;ss7_unknownprefix = +; + +; This option is used to disable automatic sending of ACM when the call is started +; in the dialplan. If you do use this option, you will need to use the Proceeding() +; application in the dialplan to send ACM or enable ss7_autoacm below. +;ss7_explicitacm=yes + +; Use this option to automatically send ACM when the call rings or is answered and +; has not seen proceeding yet. If you use this option, you should disable ss7_explicitacm. +; You may still use Proceeding() to explicitly send an ACM from the dialplan. +;ss7_autoacm=yes + +; Create the linkset with all CICs in hardware remotely blocked state. +;ss7_initialhwblo=yes + +; This option is whether or not to trust the remote echo control indication. This means +; that in cases where echo control is reported by the remote end, we will trust them and +; not enable echo cancellation on the call. +;ss7_use_echocontrol=yes + +; This option is to set what our echo control indication is to the other end. Set to +; yes to indicate that we are using echo cancellation or no if we are not. +;ss7_default_echocontrol=yes + +; All settings apply to linkset 1 +;linkset = 1 + +; Set the Signaling Link Code (SLC) for each sigchan. +; If you manually set any you need to manually set all. +; Should be defined before sigchan. +; The default SLC starts with zero and increases for each defined sigchan. +;slc= + +; Point code of the linkset. For ITU, this is the decimal number +; format of the point code. For ANSI, this can either be in decimal +; number format or in the xxx-xxx-xxx format +;pointcode = 1 + +; Point code of node adjacent to this signalling link (Possibly the STP between you and +; your destination). Point code format follows the same rules as above. +;adjpointcode = 2 + +; Default point code that you would like to assign to outgoing messages (in case of +; routing through STPs, or using A links). Point code format follows the same rules +; as above. +;defaultdpc = 3 + +; Begin CIC (Circuit indication codes) count with this number +;cicbeginswith = 1 + +; What the MTP3 network indicator bits should be set to. Choices are +; national, national_spare, international, international_spare +;networkindicator=international + +; First signalling channel +;sigchan = 48 + +; Additional signalling channel for this linkset (So you can have a linkset +; with two signalling links in it). It seems like a silly way to do it, but +; for linksets with multiple signalling links, you add an additional sigchan +; line for every additional signalling link on the linkset. +;sigchan = 96 + +; Channels to associate with CICs on this linkset +;channel = 25-47 +; + +; Set this option if you wish to send an Information Request Message (INR) request +; if no calling party number is specified. This will attempt to tell the other end +; to send it anyways. Should be defined after sigchan. +;inr_if_no_calling=yes + +; Set this to set whether or not the originating access is (non) ISDN in the forward and +; backward call indicators. Should be defined after sigchan +;non_isdn_access=yes + +; This sets the number of binary places to shift the CIC when doing load balancing between +; sigchans on a linkset. Should be defined after sigchan. Default 0 +;sls_shift = 0 + +; Send custom cause_location value +; Should be defined after sigchan. Default 1 (private local) +;cause_location=1 + +; SS7 timers (ISUP and MTP3) should be explicitly defined for each linkset to be used. +; For a full list of supported timers and their default values (applicable for both ITU +; and ANSI) see ss7.timers +; Should be defined after sigchan +;#include ss7.timers + +; For more information on setting up SS7, see the README file in libss7 or +; https://wiki.asterisk.org/wiki/display/AST/Signaling+System+Number+7 +; ----------------- SS7 Options ---------------------------------------- + +; ---------------- Options for use with signalling=mfcr2 -------------- + +; MFC-R2 signaling has lots of variants from country to country and even sometimes +; minor variants inside the same country. The only mandatory parameters here are: +; mfcr2_variant, mfcr2_max_ani and mfcr2_max_dnis. +; IT IS RECOMMENDED that you leave the default values (leaving it commented) for the +; other parameters unless you have problems or you have been instructed to change some +; parameter. OpenR2 library uses the mfcr2_variant parameter to try to determine the +; best defaults for your country, also refer to the OpenR2 package directory +; doc/asterisk/ where you can find sample configurations for some countries. If you +; want to contribute your configs for a particular country send them to the e-mail +; of the primary OpenR2 developer that you can find in the AUTHORS file of the OpenR2 package + +; MFC/R2 variant. This depends on the OpenR2 supported variants +; A list of values can be found by executing the openr2 command r2test -l +; some valid values are: +; ar (Argentina) +; br (Brazil) +; mx (Mexico) +; ph (Philippines) +; itu (per ITU spec) +; mfcr2_variant=mx + +; Max amount of ANI to ask for +; mfcr2_max_ani=10 + +; Max amount of DNIS to ask for +; mfcr2_max_dnis=4 + +; whether or not to get the ANI before getting DNIS. +; some telcos require ANI first some others do not care +; if this go wrong, change this value +; mfcr2_get_ani_first=no + +; Caller Category to send +; national_subscriber +; national_priority_subscriber +; international_subscriber +; international_priority_subscriber +; collect_call +; usually national_subscriber works just fine +; you can change this setting from the dialplan +; by setting the variable MFCR2_CATEGORY +; (remember to set _MFCR2_CATEGORY from originating channels) +; MFCR2_CATEGORY will also be a variable available in your context +; on incoming calls set to the value received from the far end +; mfcr2_category=national_subscriber + +; Call logging is stored at the Asterisk +; logging directory specified in asterisk.conf +; plus mfcr2/ +; if you specify 'span1' here and asterisk.conf has +; as logging directory /var/log/asterisk then the full +; path to your MFC/R2 call logs will be /var/log/asterisk/mfcr2/span1 +; (the directory will be automatically created if not present already) +; remember to set mfcr2_call_files=yes +; mfcr2_logdir=span1 + +; whether or not to drop call files into mfcr2_logdir +; mfcr2_call_files=yes|no + +; MFC/R2 valid logging values are: all,error,warning,debug,notice,cas,mf,stack,nothing +; error,warning,debug and notice are self-descriptive +; 'cas' is for logging ABCD CAS tx and rx +; 'mf' is for logging of the Multi Frequency tones +; 'stack' is for very verbose output of the channel and context call stack, only useful +; if you are debugging a crash or want to learn how the library works. The stack logging +; will be only enabled if the openr2 library was compiled with -DOR2_TRACE_STACKS +; You can mix up values, like: loglevel=error,debug,mf to log just error, debug and +; multi frequency messages +; 'all' is a special value to log all the activity +; 'nothing' is a clean-up value, in case you want to not log any activity for +; a channel or group of channels +; BE AWARE that the level of output logged will ALSO depend on +; the value you have in logger.conf, if you disable output in logger.conf +; then it does not matter you specify 'all' here, nothing will be logged +; so logger.conf has the last word on what is going to be logged +; mfcr2_logging=all + +; MFC/R2 value in milliseconds for the MF timeout. Any negative value +; means 'default', smaller values than 500ms are not recommended +; and can cause malfunctioning. If you experience protocol error +; due to MF timeout try incrementing this value in 500ms steps +; mfcr2_mfback_timeout=-1 + +; MFC/R2 value in milliseconds for the metering pulse timeout. +; Metering pulses are sent by some telcos for some R2 variants +; during a call presumably for billing purposes to indicate costs, +; however this pulses use the same signal that is used to indicate +; call hangup, therefore a timeout is sometimes required to distinguish +; between a *real* hangup and a billing pulse that should not +; last more than 500ms, If you experience call drops after some +; minutes of being stablished try setting a value of some ms here, +; values greater than 500ms are not recommended. +; BE AWARE that choosing the proper protocol mfcr2_variant parameter +; implicitly sets a good recommended value for this timer, use this +; parameter only when you *really* want to override the default, otherwise +; just comment out this value or put a -1 +; Any negative value means 'default'. +; mfcr2_metering_pulse_timeout=-1 + +; Brazil uses a special calling party category for collect calls (llamadas por cobrar) +; instead of using the operator (as in Mexico). The R2 spec in Brazil says a special GB tone +; should be used to reject collect calls. If you want to ALLOW collect calls specify 'yes', +; if you want to BLOCK collect calls then say 'no'. Default is to block collect calls. +; (see also 'mfcr2_double_answer') +; mfcr2_allow_collect_calls=no + +; This feature is related but independent of mfcr2_allow_collect_calls +; Some PBX's require a double-answer process to block collect calls, if +; you ever have problems blocking collect calls using Group B signals (mfcr2_allow_collect_calls=no) +; then you may want to try with mfcr2_double_answer=yes, this will cause that every answer signal +; is changed by answer->clear back->answer (sort of a flash) +; (see also 'mfcr2_allow_collect_calls') +; mfcr2_double_answer=no + +; This feature allows to skip the use of Group B/II signals and go directly +; to the accepted state for incoming calls +; mfcr2_immediate_accept=no + +; You most likely dont need this feature. Default is yes. +; When this is set to yes, all calls that are offered (incoming calls) which +; DNIS is valid (exists in extensions.conf) and pass collect call validation +; will be accepted with a Group B tone (either call with charge or not, depending on mfcr2_charge_calls) +; with this set to 'no' then the call will NOT be accepted on offered, and the call will start its +; execution in extensions.conf without being accepted until the channel is answered (either with Answer() or +; any other application resulting in the channel being answered). +; This can be set to 'no' if your telco or PBX needs the hangup cause to be set accurately +; when this option is set to no you must explicitly accept the call with DAHDIAcceptR2Call +; or implicitly through the Answer() application. +; mfcr2_accept_on_offer=yes + +; Skip request of calling party category and ANI +; you need openr2 >= 1.2.0 to use this feature +; mfcr2_skip_category=no + +; WARNING: advanced users only! I really mean it +; this parameter is commented by default because +; YOU DON'T NEED IT UNLESS YOU REALLY GROK MFC/R2 +; READ COMMENTS on doc/r2proto.conf in openr2 package +; for more info +; mfcr2_advanced_protocol_file=/path/to/r2proto.conf + +; Brazil use a special signal to force the release of the line (hangup) from the +; backward perspective. When mfcr2_forced_release=no, the normal clear back signal +; will be sent on hangup, which is OK for all mfcr2 variants I know of, except for +; Brazilian variant, where the central will leave the line up for several seconds (30, 60) +; which sometimes is not what people really want. When mfcr2_forced_release=yes, a different +; signal will be sent to hangup the call indicating that the line should be released immediately +; mfcr2_forced_release=no + +; Whether or not report to the other end 'accept call with charge' +; This setting has no effect with most telecos, usually is safe +; leave the default (yes), but once in a while when interconnecting with +; old PBXs this may be useful. +; Concretely this affects the Group B signal used to accept calls +; The application DAHDIAcceptR2Call can also be used to decide this +; in the dial plan in a per-call basis instead of doing it here for all calls +; mfcr2_charge_calls=yes + +; ---------------- END of options to be used with signalling=mfcr2 + +; Configuration Sections +; ~~~~~~~~~~~~~~~~~~~~~~ +; You can also configure channels in a separate chan_dahdi.conf section. In +; this case the keyword 'channel' is not used. Instead the keyword +; 'dahdichan' is used (as in users.conf) - configuration is only processed +; in a section where the keyword dahdichan is used. It will only be +; processed in the end of the section. Thus the following section: +; +;[phones] +;echocancel = 64 +;dahdichan = 1-8 +;group = 1 +; +; Is somewhat equivalent to the following snippet in the section +; [channels]: +; +;echocancel = 64 +;group = 1 +;channel => 1-8 +; +; When starting a new section almost all of the configuration values are +; copied from their values at the end of the section [channels] in +; chan_dahdi.conf and [general] in users.conf - one section's configuration +; does not affect another one's. +; +; Instead of letting common configuration values "slide through" you can +; use configuration templates to easily keep the common part in one +; place and override where needed. +; +;[phones](!) +;echocancel = yes +;group = 0,4 +;callgroup = 3 +;pickupgroup = 3 +;threewaycalling = yes +;transfer = yes +;context = phones +;faxdetect = incoming +; +;[phone-1](phones) +;dahdichan = 1 +;callerid = My Name <501> +;mailbox = 501@mailboxes +; +; +;[fax](phones) +;dahdichan = 2 +;faxdetect = no +;context = fax +; +;[phone-3](phones) +;dahdichan = 3 +;pickupgroup = 3,4 diff --git a/mount/asterisk/conf/chan_mobile.conf b/mount/asterisk/conf/chan_mobile.conf new file mode 100644 index 0000000..3814337 --- /dev/null +++ b/mount/asterisk/conf/chan_mobile.conf @@ -0,0 +1,69 @@ +; +; chan_mobile.conf +; configuration file for chan_mobile +; + +[general] +interval=30 ; Number of seconds between trying to connect to devices. + +; The following is a list of adapters we use. +; id must be unique and address is the bdaddr of the adapter from hciconfig. +; Each adapter may only have one device (headset or phone) connected at a time. +; Add an [adapter] entry for each adapter you have. + +[adapter] +id=blue +address=00:09:DD:60:01:A3 +;forcemaster=yes ; attempt to force adapter into master mode. default is no. +;alignmentdetection=yes ; enable this if you sometimes get 'white noise' on asterisk side of the call + ; its a bug in the bluetooth adapter firmware, enabling this will compensate for it. + ; default is no. + +[adapter] +id=dlink +address=00:80:C8:35:52:78 + +; The following is a list of the devices we deal with. +; Every device listed below will be available for calls in and out of Asterisk. +; Each device needs an adapter=xxxx entry which determines which bluetooth adapter is used. +; Use the CLI command 'mobile search' to discover devices. +; Use the CLI command 'mobile show devices' to see device status. +; +; To place a call out through a mobile phone use Dial(Mobile/[device]/NNN.....) or Dial(Mobile/gn/NNN......) in your dialplan. +; To call a headset use Dial(Mobile/[device]). + +[LGTU550] +address=00:E0:91:7F:46:44 ; the address of the phone +port=4 ; the rfcomm port number (from mobile search) +context=incoming-mobile ; dialplan context for incoming calls +adapter=dlink ; adapter to use +group=1 ; this phone is in channel group 1 +;sms=no ; support SMS, defaults to yes +;nocallsetup=yes ; set this only if your phone reports that it supports call progress notification, but does not do it. Motorola L6 for example. + +[blackberry] +address=00:60:57:32:7E:B2 +port=2 +context=incoming-mobile +adapter=dlink +group=1 +;blackberry=yes ; set this if you are using a blackberry device + +[6310i] +address=00:60:57:32:7E:B1 +port=13 +context=incoming-mobile +adapter=dlink +group=1 ; this phone is in channel group 1 also. + +[headset] +address=00:0B:9E:11:AE:C6 +port=1 +type=headset ; This is a headset, not a Phone ! +adapter=blue + +[headset1] +address=00:0B:9E:11:74:A5 +port=1 +type=headset +adapter=dlink diff --git a/mount/asterisk/conf/cli.conf b/mount/asterisk/conf/cli.conf new file mode 100644 index 0000000..0ddd92c --- /dev/null +++ b/mount/asterisk/conf/cli.conf @@ -0,0 +1,12 @@ +; +; Asterisk CLI configuration +; + +[startup_commands] +; +; Any commands listed in this section will get automatically executed +; when Asterisk starts as a daemon or foreground process (-c). +; +;sip set debug on = yes +;core set verbose 3 = yes +;core set debug 1 = yes diff --git a/mount/asterisk/conf/cli_aliases.conf b/mount/asterisk/conf/cli_aliases.conf new file mode 100644 index 0000000..adaed90 --- /dev/null +++ b/mount/asterisk/conf/cli_aliases.conf @@ -0,0 +1,203 @@ +; +; CLI Aliases configuration +; +; This module also registers a "cli show aliases" CLI command to list +; configured CLI aliases. + +[general] +; Here you define what alias templates you want to use. You can also define +; multiple templates to use as well. If you do, and there is a conflict, then +; the first alias defined will win. +; +template = friendly ; By default, include friendly aliases +;template = asterisk_1dot2 ; Asterisk 1.2 style syntax +;template = asterisk_1dot4 ; Asterisk 1.4 style syntax +;template = individual_custom ; see [individual_custom] example below which + ; includes a list of aliases from an external + ; file + + +; Because the Asterisk CLI syntax follows a "module verb argument" syntax, +; sometimes we run into an issue between being consistant with this format +; in the core system, and maintaining system friendliness. In order to get +; around this we're providing some useful aliases by default. +; +[friendly] +hangup request=channel request hangup +originate=channel originate +help=core show help +pri intense debug span=pri set debug intense span +reload=module reload +pjsip reload=module reload res_pjsip.so res_pjsip_authenticator_digest.so res_pjsip_endpoint_identifier_ip.so res_pjsip_mwi.so res_pjsip_notify.so res_pjsip_outbound_publish.so res_pjsip_publish_asterisk.so res_pjsip_outbound_registration.so + +; CLI Alias Templates +; ------------------- +; +; You can define several alias templates. +; It works with context templates like all other configuration files +; +;[asterisk](!) +; To create an alias you simply set the variable name as the alias and variable +; value as the real CLI command you want executed +; +;die die die=stop now + +;[asterisk_1dot6](asterisk) +; Alias for making voicemail reload actually do module reload app_voicemail.so +;voicemail reload=module reload app_voicemail.so +; This will make the CLI command "mr" behave as though it is "module reload". +;mr=module reload +; +; +; In addition, you could also include a flat file of aliases which is loaded by +; the [individual_custom] template in the [general] section. +; +;[individual_custom] +;#include "/etc/asterisk/aliases" + +; Implemented CLI Alias Templates +; ------------------------------- +; +; Below here we have provided you with some templates, easily allowing you to +; utilize previous Asterisk CLI commands with any version of Asterisk. In this +; way you will be able to use Asterisk 1.2 and 1.4 style CLI syntax with any +; version Asterisk going forward into the future. +; +; We have also separated out the vanilla syntax into a context template which +; allows you to keep your custom changes separate of the standard templates +; we have provided you. In this way you can clearly see your custom changes, +; and also allowing you to combine various templates as you see fit. +; +; The naming scheme we have used is recommended, but certainly is not enforced +; by Asterisk. If you wish to use the provided templates, simply define the +; context name which does not utilize the '_tpl' at the end. For example, +; if you would like to use the Asterisk 1.2 style syntax, define in the +; [general] section + +[asterisk_1dot2_tpl](!) +show channeltypes=core show channeltypes +show channeltype=core show channeltype +show manager command=manager show command +show manager commands=manager show commands +show manager connected=manager show connected +show manager eventq=manager show eventq +rtp no debug=rtp set debug off +rtp rtcp debug ip=rtcp debug ip +rtp rtcp debug=rtcp debug +rtp rtcp no debug=rtcp debug off +rtp rtcp stats=rtcp stats +rtp rtcp no stats=rtcp stats off +stun no debug=stun debug off +udptl no debug=udptl debug off +show image formats=core show image formats +show file formats=core show file formats +show applications=core show applications +show functions=core show functions +show switches=core show switches +show hints=core show hints +show globals=core show globals +show function=core show function +show application=core show application +set global=core set global +show dialplan=dialplan show +show codecs=core show codecs +show audio codecs=core show audio codecs +show video codecs=core show video codecs +show image codecs=core show image codecs +show codec=core show codec +moh classes show=moh show classes +moh files show=moh show files +agi no debug=agi debug off +show agi=agi show +dump agihtml=agi dumphtml +show features=feature show +show indications=indication show +answer=console answer +hangup=console hangup +flash=console flash +dial=console dial +mute=console mute +unmute=console unmute +transfer=console transfer +send text=console send text +autoanswer=console autoanswer +oss boost=console boost +console=console active +save dialplan=dialplan save +add extension=dialplan add extension +remove extension=dialplan remove extension +add ignorepat=dialplan add ignorepat +remove ignorepat=dialplan remove ignorepat +include context=dialplan add include +dont include=dialplan remove include +extensions reload=dialplan reload +show translation=core show translation +convert=file convert +show queue=queue show +add queue member=queue add member +remove queue member=queue remove member +ael no debug=ael nodebug +sip debug=sip set debug +sip no debug=sip set debug off +show voicemail users=voicemail show users +show voicemail zones=voicemail show zones +iax2 trunk debug=iax2 set debug trunk +iax2 jb debug=iax2 set debug jb +iax2 no debug=iax2 set debug off +iax2 no trunk debug=iax2 set debug trunk off +iax2 no jb debug=iax2 set debug jb off +show agents=agent show +show agents online=agent show online +show memory allocations=memory show allocations +show memory summary=memory show summary +show version=core show version +show version files=core show file version +show profile=core show profile +clear profile=core clear profile +soft hangup=channel request hangup + +[asterisk_1dot2](asterisk_1dot2_tpl) +; add any additional custom commands you want below here, for example: +;die quickly=stop now + +[asterisk_1dot4_tpl](!) +cdr status=cdr show status +rtp debug=rtp set debug on +rtcp debug=rtcp set debug on +rtcp stats=rtcp set stats on +stun debug=stun set debug on +udptl debug=udptl set debug on +core show globals=dialplan show globals +core set global=dialplan set global +core set chanvar=dialplan set chanvar +agi dumphtml=agi dump html +ael debug=ael set debug +funcdevstate list=devstate list +sip history=sip set history on +skinny debug=skinny set debug on +mgcp set debug=mgcp set debug on +abort shutdown=core abort shutdown +stop now=core stop now +stop gracefully=core stop gracefully +stop when convenient=core stop when convenient +restart now=core restart now +restart gracefully=core restart gracefully +restart when convenient=core restart when convenient +soft hangup=channel request hangup + +[asterisk_1dot4](asterisk_1dot4_tpl) +; add any additional custom commands you want below here. + +[asterisk_11_tpl](!) +jabber list nodes=xmpp list nodes +jabber purge nodes=xmpp purge nodes +jabber delete node=xmpp delete node +jabber create collection=xmpp create collection +jabber create leaf=xmpp create leaf +jabber set debug=xmpp set debug +jabber show connections=xmpp show connections +jabber show buddies=xmpp show buddies +features reload=module reload features + +[asterisk_11](asterisk_11_tpl) +; add any additional custom commands you want below here. diff --git a/mount/asterisk/conf/cli_permissions.conf b/mount/asterisk/conf/cli_permissions.conf new file mode 100644 index 0000000..4a6973f --- /dev/null +++ b/mount/asterisk/conf/cli_permissions.conf @@ -0,0 +1,82 @@ +; +; CLI permissions configuration example for Asterisk +; +; All the users that you want to connect with asterisk using +; rasterisk, should have write/read access to the +; asterisk socket (asterisk.ctl). You could change the permissions +; of this file in 'asterisk.conf' config parameter: 'astctlpermissions' (0666) +; found on the [files] section. +; +; general options: +; +; default_perm = permit | deny +; This is the default permissions to apply for a user that +; does not has a permissions definided. +; +; user options: +; permit = | all ; allow the user to run 'command' | +; ; allow the user to run 'all' the commands +; deny = | all ; disallow the user to run 'command' | +; ; disallow the user to run 'all' commands. +; + +[general] + +default_perm=permit ; To leave asterisk working as normal + ; we should set this parameter to 'permit' +; +; Follows the per-users permissions configs. +; +; This list is read in the sequence that is being written, so +; In this example the user 'eliel' is allow to run only the following +; commands: +; sip show peer +; core set debug +; core set verbose +; If the user is not specified, the default_perm option will be apply to +; every command. +; +; Notice that you can also use regular expressions to allow or deny access to a +; certain command like: 'core show application D*'. In this example the user will be +; allowed to view the documentation for all the applications starting with 'D'. +; Another regular expression could be: 'channel originate SIP/[0-9]* extension *' +; allowing the user to use 'channel originate' on a sip channel and with the 'extension' +; parameter and avoiding the use of the 'application' parameter. +; +; We can also use the templates syntax: +; [supportTemplate](!) +; deny=all +; permit=sip show ; all commands starting with 'sip show' will be allowed +; permit=core show +; +; You can specify permissions for a local group instead of a user, +; just put a '@' and we will know that is a group. +; IMPORTANT NOTE: Users permissions overwrite group permissions. +; +;[@adm] +;deny=all +;permit=sip +;permit=core +; +; +;[eliel] +;deny=all +;permit=sip show peer +;deny=sip show peers +;permit=core set +; +; +;User 'tommy' inherits from template 'supportTemplate': +; deny=all +; permit=sip show +; permit=core show +;[tommy](supportTemplate) +;permit=core set debug +;permit=dialplan show +; +; +;[mark] +;deny=all +;permit=all +; +; diff --git a/mount/asterisk/conf/codecs.conf b/mount/asterisk/conf/codecs.conf new file mode 100644 index 0000000..ef5a2f8 --- /dev/null +++ b/mount/asterisk/conf/codecs.conf @@ -0,0 +1,214 @@ +[speex] +; CBR encoding quality [0..10] +; used only when vbr = false +quality => 3 + +; codec complexity [0..10] +; tradeoff between cpu/quality +complexity => 2 + +; perceptual enhancement [true / false] +; improves clarity of decoded speech +enhancement => true + +; voice activity detection [true / false] +; reduces bitrate when no voice detected, used only for CBR +; (implicit in VBR/ABR) +vad => true + +; variable bit rate [true / false] +; uses bit rate proportionate to voice complexity +vbr => true + +; available bit rate [bps, 0 = off] +; encoding quality modulated to match this target bit rate +; not recommended with dtx or pp_vad - may cause bandwidth spikes +abr => 0 + +; VBR encoding quality [0-10] +; floating-point values allowed +vbr_quality => 4 + +; discontinuous transmission [true / false] +; stops transmitting completely when silence is detected +; pp_vad is far more effective but more CPU intensive +dtx => false + +; preprocessor configuration +; these options only affect Speex v1.1.8 or newer + +; enable preprocessor [true / false] +; allows dsp functionality below but incurs CPU overhead +preprocess => false + +; preproc voice activity detection [true / false] +; more advanced equivalent of DTX, based on voice frequencies +pp_vad => false + +; preproc automatic gain control [true / false] +pp_agc => false +pp_agc_level => 8000 + +; preproc denoiser [true / false] +pp_denoise => false + +; preproc dereverb [true / false] +pp_dereverb => false +pp_dereverb_decay => 0.4 +pp_dereverb_level => 0.3 + +; experimental bitrate changes depending on RTCP feedback [true / false] +experimental_rtcp_feedback => false + + +[plc] +; for all codecs which do not support native PLC +; this determines whether to perform generic PLC +; there is a minor performance penalty for this. +; By default plc is applied only when the 2 codecs +; in a channel are different. +genericplc => true +; Apply generic plc to channels even if the 2 codecs +; are the same. This forces transcoding via slin so +; the performance impact should be considered. +; Ignored if genericplc is not also enabled. +genericplc_on_equal_codecs => false + +; Generate custom formats for formats requiring attributes. +; After defining the custom format, the name used in defining +; the format can be used throughout Asterisk in the format 'allow' +; and 'disallow' options. +; +; Example: silk8 is a predefined custom format in this config file. +; Once this config file is loaded, silk8 can be used anywhere a +; peer's codec capabilities are defined. +; +; In sip.conf 'silk8' can be defined as a capability for a peer. +; [peer1] +; type=peer +; host=dynamic +; disallow=all +; allow=silk8 ;custom codec defined in codecs.conf +; +; LIMITATIONS +; Custom formats can only be defined at startup. Any changes to this +; file made after startup will not take into effect until after Asterisk +; is restarted. +; + +; Default Custom SILK format definitions, only one custom SILK format per +; sample rate is allowed. +[silk8] +type=silk +samprate=8000 +fec=true ; turn on or off encoding with forward error correction. + ; On recommended, off by default. +packetloss_percentage=10 ; Estimated packet loss percentage in uplink direction. This + ; affects how much redundancy is built in when using fec. + ; The higher the percentage, the larger amount of bandwidth is + ; used. Default is 0%, 10% is recommended when fec is in use. + +maxbitrate=10000 ; Use the table below to make sure a useful bitrate is choosen + ; for maxbitrate. If not set or value is not within the bounds + ; of the encoder, a default value is chosen. + ; + ; sample rate | bitrate range + ; 8khz | 5000 - 20000 bps + ; 12khz | 7000 - 25000 bps + ; 16khz | 8000 - 30000 bps + ; 24khz | 20000- 40000 bps + ; +;dtx=true ; Encode using discontinuous transmission mode or not. Turning this + ; on will save bandwidth during periods of silence at the cost of + ; increased computational complexity. Off by default. + +[silk12] +type=silk +samprate=12000 +maxbitrate=12000 +fec=true +packetloss_percentage=10; + +[silk16] +type=silk +samprate=16000 +maxbitrate=20000 +fec=true +packetloss_percentage=10; + +[silk24] +type=silk +samprate=24000 +maxbitrate=30000 +fec=true +packetloss_percentage=10; + + +; Default custom CELT codec definitions. Only one custom CELT definition is allowed +; per a sample rate. +;[celt44] +;type=celt +;samprate=44100 ; The samplerate in hz. This option is required. +;framesize=480 ; The framesize option represents the duration of each frame in samples. + ; This must be a factor of 2. This option is only advertised in an SDP + ; when it is set. Otherwise a default of framesize of 480 is assumed + ; internally + +;[celt48] +;type=celt +;samprate=48000 + +;[celt32] +;type=celt +;samprate=32000 + +;============================ OPUS Section Options ============================ +; +; NOTE: Accurate documentation corresponding to your downloaded version of +; codec_opus is available from Asterisk's CLI: +; +; *CLI> config show help codec_opus opus +; +;[opus] +;type= ; Must be of type "opus" (default: "") +;packet_loss= ; Encoder's packet loss percentage. Can be any number between 0 + ; and 100, inclusive. A higher value results in more loss + ; resistance. (default: 0) +;complexity= ; Encoder's computational complexity. Can be any number between 0 + ; and 10, inclusive. Note, 10 equals the highest complexity. + ; (default: 10) +;max_bandwidth= ; Encoder's maximum bandwidth allowed. Sets an upper bandwidth + ; bound on the encoder. Can be any of the following: narrow, + ; medium, wide, super_wide, full. (default: full) +;signal= ; Encoder's signal type. Aids in mode selection on the encoder: Can + ; be any of the following: auto, voice, music. (default: auto) +;application= ; Encoder's application type. Can be any of the following: voip, + ; audio, low_delay. (default: voip) +;max_playback_rate= ; Override the maximum playback rate in the offer's SDP. + ; Any value between 8000 and 48000 (inclusive) is valid, + ; however typically it should match one of the usual opus + ; bandwidths. (default: 48000) +;bitrate= ; Override the maximum average bitrate in the offer's SDP. Any value + ; between 500 and 512000 is valid. The following values are also + ; allowed: auto, max. (default: auto) +;cbr= ; Override the constant bit rate parameter in the offer's SDP. A value of + ; 0/false/no represents a variable bit rate whereas 1/true/yes represents + ; a constant bit rate. (default: no) +;fec= ; Override the use inband fec parameter in the offer's SDP. A value of + ; 0/false/no represents disabled whereas 1/true/yes represents enabled. + ; (default: yes) +;dtx= ; Override the use dtx parameter in the offer's SDP. A value of 0/false/no + ; represents disabled whereas 1/true/yes represents enabled. (default: no) + +;=============================== OPUS Examples ================================ +; +;[opus] +;type=opus +;max_playback_rate=8000 ; Limit the maximum playback rate on the encoder +;fec=no ; No inband fec + +;[myopus] +;type=opus +;max_bandwidth=wide ; Maximum encoded bandwidth set to wide band (0-8000 Hz +; ; audio bandwidth at 16Khz sample rate) +;cbr=yes ; Negotiate a constant bit rate diff --git a/mount/asterisk/conf/confbridge.conf b/mount/asterisk/conf/confbridge.conf new file mode 100644 index 0000000..7749c93 --- /dev/null +++ b/mount/asterisk/conf/confbridge.conf @@ -0,0 +1,450 @@ +[general] +; The general section of this config +; is not currently used, but reserved +; for future use. + +; +; --- Default Information --- +; The default_user and default_bridge sections are applied +; automatically to all ConfBridge instances invoked without +; a user, or bridge argument. No menu is applied by default. +; +; Note that while properties of the default_user or default_bridge +; profile can be overridden, if removed, they will be automatically +; added and made available to the dialplan upon module load. +; + +; --- ConfBridge User Profile Options --- +[default_user] +type=user +;admin=yes ; Sets if the user is an admin or not. Off by default. + +;send_events=no ; If events are enabled for this bridge and this option is + ; set, users will receive events like join, leave, talking, + ; etc. via text messages. For users accessing the bridge + ; via chan_pjsip, this means in-dialog MESSAGE messages. + ; This is most useful for WebRTC participants where the + ; browser application can use the messages to alter the user + ; interface. +;echo_events=yes ; If events are enabled for this user and this option is set, + ; the user will receive events they trigger, talking, mute, etc. + ; If not set, they will not receive their own events. + +;marked=yes ; Sets if this is a marked user or not. Off by default. +;startmuted=yes; Sets if all users should start out muted. Off by default +;music_on_hold_when_empty=yes ; Sets whether MOH should be played when only + ; one person is in the conference or when the + ; the user is waiting on a marked user to enter + ; the conference. Off by default. +;music_on_hold_class=default ; The MOH class to use for this user. +;quiet=yes ; When enabled enter/leave prompts and user intros are not played. + ; There are some prompts, such as the prompt to enter a PIN number, + ; that must be played regardless of what this option is set to. + ; Off by default +;announce_user_count=yes ; Sets if the number of users should be announced to the + ; caller. Off by default. +;announce_user_count_all=yes ; Sets if the number of users should be announced to + ; all the other users in the conference when someone joins. + ; This option can be either set to 'yes' or a number. + ; When set to a number, the announcement will only occur + ; once the user count is above the specified number. +;announce_only_user=yes ; Sets if the only user announcement should be played + ; when a channel enters a empty conference. On by default. +;wait_marked=yes ; Sets if the user must wait for a marked user to enter before + ; joining the conference. Off by default. +;end_marked=yes ; This option will kick every user with this option set in their + ; user profile after the last Marked user exists the conference. + +;dsp_drop_silence=yes ; This option drops what Asterisk detects as silence from + ; entering into the bridge. Enabling this option will drastically + ; improve performance and help remove the buildup of background + ; noise from the conference. Highly recommended for large conferences + ; due to its performance enhancements. + +;dsp_talking_threshold=128 ; Average magnitude threshold to determine talking. + ; + ; The minimum average magnitude per sample in a frame for the + ; DSP to consider talking/noise present. A value below this + ; level is considered silence. This value affects several + ; operations and should not be changed unless the impact on + ; call quality is fully understood. + ; + ; What this value affects internally: + ; + ; 1. Audio is only mixed out of a user's incoming audio + ; stream if talking is detected. If this value is set too + ; high the user will hear himself talking. + ; + ; 2. When talk detection AMI events are enabled, this value + ; determines when talking has begun which results in an + ; AMI event to fire. If this value is set too low AMI + ; events may be falsely triggered by variants in room + ; noise. + ; + ; 3. The 'drop_silence' option depends on this value to + ; determine when the user's audio should be mixed into the + ; bridge after periods of silence. If this value is too + ; high the user's speech will get discarded as they will + ; be considered silent. + ; + ; Valid values are 1 through 2^15. + ; By default this value is 160. + +;dsp_silence_threshold=2000 ; The number of milliseconds of silence necessary to declare + ; talking stopped. + ; + ; The time in milliseconds of sound falling below the + ; 'dsp_talking_threshold' option when a user is considered to + ; stop talking. This value affects several operations and + ; should not be changed unless the impact on call quality is + ; fully understood. + ; + ; What this value affects internally: + ; + ; 1. When talk detection AMI events are enabled, this value + ; determines when the user has stopped talking after a + ; period of talking. If this value is set too low AMI + ; events indicating the user has stopped talking may get + ; falsely sent out when the user briefly pauses during mid + ; sentence. + ; + ; 2. The 'drop_silence' option depends on this value to + ; determine when the user's audio should begin to be + ; dropped from the conference bridge after the user stops + ; talking. If this value is set too low the user's audio + ; stream may sound choppy to the other participants. This + ; is caused by the user transitioning constantly from + ; silence to talking during mid sentence. + ; + ; The best way to approach this option is to set it slightly + ; above the maximum amount of milliseconds of silence a user + ; may generate during natural speech. + ; + ; Valid values are 1 through 2^31. + ; By default this value is 2500ms. + +;talk_detection_events=yes ; This option sets whether or not notifications of when a user + ; begins and ends talking should be sent out as events over AMI. + ; By default this option is off. + +;denoise=yes ; Sets whether or not a denoise filter should be applied + ; to the audio before mixing or not. Off by default. Requires + ; func_speex to be built and installed. Do not confuse this option + ; with drop_silence. Denoise is useful if there is a lot of background + ; noise for a user as it attempts to remove the noise while preserving + ; the speech. This option does NOT remove silence from being mixed into + ; the conference and does come at the cost of a slight performance hit. + +;jitterbuffer=yes ; Enabling this option places a jitterbuffer on the user's audio stream + ; before audio mixing is performed. This is highly recommended but will + ; add a slight delay to the audio. This option is using the JITTERBUFFER + ; dialplan function's default adaptive jitterbuffer. For a more fine tuned + ; jitterbuffer, disable this option and use the JITTERBUFFER dialplan function + ; on the user before entering the ConfBridge application. + +;pin=1234 ; Sets if this user must enter a PIN number before entering + ; the conference. The PIN will be prompted for. +;announce_join_leave=yes ; When enabled, this option will prompt the user for a + ; name when entering the conference. After the name is + ; recorded, it will be played as the user enters and exists + ; the conference. This option is off by default. +;announce_join_leave_review=yes ; When enabled, implies announce_join_leave, but the user + ; will be prompted to review their recording before + ; entering the conference. During this phase, the recording + ; may be listened to, re-recorded, or accepted as is. This + ; option is off by default. +;dtmf_passthrough=yes ; Sets whether or not DTMF should pass through the conference. + ; This option is off by default. +;announcement= ; Play a sound file to the user when they join the conference. + +;timeout=3600 ; When set non-zero, this specifies the number of seconds that the participant + ; may stay in the conference before being automatically ejected. When the user + ; is ejected from the conference, the user's channel will have the CONFBRIDGE_RESULT + ; variable set to "TIMEOUT". A value of 0 indicates that there is no timeout. + ; Default: 0 +;text_messaging=yes ; When set to yes text messages will be sent to this user. Text messages + ; may occur as a result of events or can be received from other participants. + ; When set to no text messages will not be sent to this user. + +; --- ConfBridge Bridge Profile Options --- +[default_bridge] +type=bridge +;max_members=50 ; This option limits the number of participants for a single + ; conference to a specific number. By default conferences + ; have no participant limit. After the limit is reached, the + ; conference will be locked until someone leaves. Note however + ; that an Admin user will always be alowed to join the conference + ; regardless if this limit is reached or not. + +;record_conference=yes ; Records the conference call starting when the first user + ; enters the room, and ending when the last user exits the room. + ; The default recorded filename is + ; 'confbridge--.wav + ; and the default format is 8khz slinear. This file will be + ; located in the configured monitoring directory in asterisk.conf. + +;record_file= ; When record_conference is set to yes, the specific name of the + ; record file can be set using this option. Note that since multiple + ; conferences may use the same bridge profile, this may cause issues + ; depending on the configuration. It is recommended to only use this + ; option dynamically with the CONFBRIDGE() dialplan function. This + ; allows the record name to be specified and a unique name to be chosen. + ; By default, the record_file is stored in Asterisk's spool/monitor directory + ; with a unique filename starting with the 'confbridge' prefix. + +;record_file_append=yes ; Append record file when starting/stopping on same conference recording. +;record_file_timestamp=yes ; Append the start time to the record file name. + +;record_options= ; Pass additional options to MixMonitor. +;record_command= ; Command to execute when recording finishes. + +;internal_sample_rate=auto ; Sets the internal native sample rate the + ; conference is mixed at. This is set to automatically + ; adjust the sample rate to the best quality by default. + ; Other values can be anything from 8000-192000. If a + ; sample rate is set that Asterisk does not support, the + ; closest sample rate Asterisk does support to the one requested + ; will be used. + +;maximum_sample_rate=none ; Sets the maximum sample rate the conference + ; is mixed at. This is set to no maximum by default. + ; Values can be anything from 8000-192000. + +;mixing_interval=40 ; Sets the internal mixing interval in milliseconds for the bridge. This + ; number reflects how tight or loose the mixing will be for the conference. + ; In order to improve performance a larger mixing interval such as 40ms may + ; be chosen. Using a larger mixing interval comes at the cost of introducing + ; larger amounts of delay into the bridge. Valid values here are 10, 20, 40, + ; or 80. By default 20ms is used. + +;video_mode = follow_talker; Sets how confbridge handles video distribution to the conference participants. + ; Note that participants wanting to view and be the source of a video feed + ; _MUST_ be sharing the same video codec. Also, using video in conjunction with + ; with the jitterbuffer currently results in the audio being slightly out of sync + ; with the video. This is a result of the jitterbuffer only working on the audio + ; stream. It is recommended to disable the jitterbuffer when video is used. + ; + ; --- MODES --- + ; none: No video sources are set by default in the conference. It is still + ; possible for a user to be set as a video source via AMI or DTMF action + ; at any time. + ; + ; follow_talker: The video feed will follow whoever is talking and providing video. + ; + ; last_marked: The last marked user to join the conference with video capabilities + ; will be the single source of video distributed to all participants. + ; If multiple marked users are capable of video, the last one to join + ; is always the source, when that user leaves it goes to the one who + ; joined before them. + ; + ; first_marked: The first marked user to join the conference with video capabilities + ; is the single source of video distribution among all participants. If + ; that user leaves, the marked user to join after them becomes the source. + ; + ; sfu: Selective Forwarding Unit - Sets multi-stream operation + ; for a multi-party video conference. + +;language=en ; Set the language used for announcements to the conference. + ; Default is en (English). + +;regcontext=conferences ; The name of the context into which to register conference names as extensions. +;video_update_discard=2000 ; Amount of time (in milliseconds) to discard video update requests after sending a video + ; update request. Default is 2000. A video update request is a request for a full video + ; intra-frame. Clients can request this if they require a full frame in order to decode + ; the video stream. Since a full frame can be large limiting how often they occur can + ; reduce bandwidth usage at the cost of increasing how long it may take a newly joined + ; channel to receive the video stream. +;remb_send_interval=1000 ; Interval (in milliseconds) at which a combined REMB frame will be sent to sources of video. + ; A REMB frame contains receiver estimated maximum bitrate information. By creating a combined + ; frame and sending it to the sources of video the sender can be influenced on what bitrate + ; they choose allowing a better experience for the receivers. This defaults to 0, or disabled. +;remb_behavior=average ; How the combined REMB report for an SFU video bridge is constructed. If set to "average" then + ; the estimated maximum bitrate of each receiver is used to construct an average bitrate. If + ; set to "lowest" the lowest maximum bitrate is forwarded to the sender. If set to "highest" + ; the highest maximum bitrate is forwarded to the sender. If set to "average_all" a single average + ; is generated from every receiver and the same value is sent to every sender. If set to + ; "lowest_all" the lowest maximum bitrate of all receivers is sent to every sender. If set to + ; "highest_all" the highest maximum bitrate of all receivers is sent to every sender. + ; When set to "force", the value set in remb_estimated_bitrate is sent to every sender. + ; This defaults to "average". +;remb_estimated_bitrate=0 ; When remb_behavior is set to 'force', this options sets the estimated bitrate + ; (in bits per second) sent to each participant in REMB reports. + +;enable_events=no ; If enabled, recipients who joined the bridge via a channel driver + ; that supports Enhanced Messaging (currently only chan_pjsip) will + ; receive in-dialog messages containing a JSON body describing the + ; event. The Content-Type header will be + ; "text/x-ast-confbridge-event". + ; This feature must also be enabled in user profiles. + +; All sounds in the conference are customizable using the bridge profile options below. +; Simply state the option followed by the filename or full path of the filename after +; the option. Example: sound_had_joined=conf-hasjoin This will play the conf-hasjoin +; sound file found in the sounds directory when announcing someone's name is joining the +; conference. + +;sound_join ; The sound played to everyone when someone enters the conference. +;sound_leave ; The sound played to everyone when someone leaves the conference. +;sound_has_joined ; The sound played before announcing someone's name has + ; joined the conference. This is used for user intros. + ; Example "_____ has joined the conference" +;sound_has_left ; The sound played when announcing someone's name has + ; left the conference. This is used for user intros. + ; Example "_____ has left the conference" +;sound_kicked ; The sound played to a user who has been kicked from the conference. +;sound_muted ; The sound played when the mute option is toggled on using DTMF menu. +;sound_unmuted ; The sound played when the mute option is toggled off using DTMF menu. +;sound_only_person ; The sound played when the user is the only person in the conference. +;sound_only_one ; The sound played to a user when there is only one other + ; person is in the conference. +;sound_there_are ; The sound played when announcing how many users there + ; are in a conference. +;sound_other_in_party; ; This file is used in conjunction with 'sound_there_are" + ; when announcing how many users there are in the conference. + ; The sounds are stringed together like this. + ; "sound_there_are" "sound_other_in_party" +;sound_place_into_conference ; The sound played when someone is placed into the conference + ; after waiting for a marked user. This sound is now deprecated + ; since it was only ever used improperly and correcting that bug + ; made it completely unused. +;sound_wait_for_leader ; The sound played when a user is placed into a conference that + ; can not start until a marked user enters. +;sound_leader_has_left ; The sound played when the last marked user leaves the conference. +;sound_get_pin ; The sound played when prompting for a conference pin number. +;sound_invalid_pin ; The sound played when an invalid pin is entered too many times. +;sound_locked ; The sound played to a user trying to join a locked conference. +;sound_locked_now ; The sound played to an admin after toggling the conference to locked mode. +;sound_unlocked_now; The sound played to an admin after toggling the conference to unlocked mode. +;sound_error_menu ; The sound played when an invalid menu option is entered. +;sound_begin ; The sound played to the conference when the first marked user enters the conference. +;sound_binaural_on ; The sound played when binaural audio is turned on +;sound_binaural_off ; The sound played when binaural audio is turned off + +; --- ConfBridge Menu Options --- +; The ConfBridge application also has the ability to +; apply custom DTMF menus to each channel using the +; application. Like the User and Bridge profiles +; a menu is passed in to ConfBridge as an argument in +; the dialplan. +; +; Below is a list of menu actions that can be assigned +; to a DTMF sequence. +; +; To have the first DTMF digit in a sequence be the '#' character, you need to +; escape it. If it is not escaped then normal config file processing will +; think it is a directive like #include. For example: +; \#1=toggle_mute ; Pressing #1 will toggle the mute setting. +; +; A single DTMF sequence can have multiple actions associated with it. This is +; accomplished by stringing the actions together and using a ',' as the delimiter. +; Example: Both listening and talking volume is reset when '5' is pressed. +; 5=reset_talking_volume, reset_listening_volume +; +; playback(&) + ; Playback will play back an audio file to a channel + ; and then immediately return to the conference. + ; This file can not be interupted by DTMF. + ; Mutliple files can be chained together using the + ; '&' character. +; playback_and_continue(&) + ; playback_and_continue will + ; play back a prompt while continuing to + ; collect the dtmf sequence. This is useful + ; when using a menu prompt that describes all + ; the menu options. Note however that any DTMF + ; during this action will terminate the prompts + ; playback. Prompt files can be chained together + ; using the '&' character as a delimiter. +; toggle_mute ; Toggle turning on and off mute. Mute will make the user silent + ; to everyone else, but the user will still be able to listen in. +; toggle_binaural ; Toggle on or off binaural audio processing. + +; no_op ; This action does nothing (No Operation). Its only real purpose exists for + ; being able to reserve a sequence in the config as a menu exit sequence. +; decrease_listening_volume ; Decreases the channel's listening volume. +; increase_listening_volume ; Increases the channel's listening volume. +; reset_listening_volume ; Reset channel's listening volume to default level. + +; decrease_talking_volume ; Decreases the channel's talking volume. +; increase_talking_volume ; Icreases the channel's talking volume. +; reset_talking_volume ; Reset channel's talking volume to default level. +; +; dialplan_exec(context,exten,priority) ; The dialplan_exec action allows a user + ; to escape from the conference and execute + ; commands in the dialplan. Once the dialplan + ; exits the user will be put back into the + ; conference. The possibilities are endless! +; leave_conference ; This action allows a user to exit the conference and continue + ; execution in the dialplan. +; +; admin_kick_last ; This action allows an Admin to kick the last participant from the + ; conference. This action will only work for admins which allows + ; a single menu to be used for both users and admins. +; +; admin_toggle_conference_lock ; This action allows an Admin to toggle locking and + ; unlocking the conference. Non admins can not use + ; this action even if it is in their menu. + +; set_as_single_video_src ; This action allows any user to set themselves as the + ; single video source distributed to all participants. + ; This will make the video feed stick to them regardless + ; of what the video_mode is set to. + +; release_as_single_video_src ; This action allows a user to release themselves as + ; the video source. If video_mode is not set to "none" + ; this action will result in the conference returning to + ; whatever video mode the bridge profile is using. + ; + ; Note that this action will have no effect if the user + ; is not currently the video source. Also, the user is + ; not guaranteed by using this action that they will not + ; become the video source again. The bridge will return + ; to whatever operation the video_mode option is set to + ; upon release of the video src. + +; admin_toggle_mute_participants ; This action allows an administrator to toggle the mute + ; state for all non-admins within a conference. + ; Subsequent non-admins joining a muted conference will + ; start muted. All admin users are unaffected by this + ; option. Note that all users, regardless of their admin + ; status, are notified that the conference is muted when + ; the state is toggled. + +; participant_count ; This action plays back the number of participants currently + ; in a conference + +[sample_user_menu] +type=menu +*=playback_and_continue(conf-usermenu) +*1=toggle_mute +1=toggle_mute +*4=decrease_listening_volume +4=decrease_listening_volume +*6=increase_listening_volume +6=increase_listening_volume +*7=decrease_talking_volume +7=decrease_talking_volume +*8=leave_conference +8=leave_conference +*9=increase_talking_volume +9=increase_talking_volume + +[sample_admin_menu] +type=menu +*=playback_and_continue(conf-adminmenu) +*1=toggle_mute +1=toggle_mute +*2=admin_toggle_conference_lock ; only applied to admin users +2=admin_toggle_conference_lock ; only applied to admin users +*3=admin_kick_last ; only applied to admin users +3=admin_kick_last ; only applied to admin users +*4=decrease_listening_volume +4=decrease_listening_volume +*6=increase_listening_volume +6=increase_listening_volume +*7=decrease_talking_volume +7=decrease_talking_volume +*8=no_op +8=no_op +*9=increase_talking_volume +9=increase_talking_volume diff --git a/mount/asterisk/conf/config_test.conf b/mount/asterisk/conf/config_test.conf new file mode 100644 index 0000000..b7cb212 --- /dev/null +++ b/mount/asterisk/conf/config_test.conf @@ -0,0 +1,46 @@ +; Config to test config parsing +; global and item have values that differ from defaults +; global_defaults and item_defualts are to show all defaults are set +; there should be an option for every default type, and a custom type + +[global] +intopt=-1 +uintopt=1 +timelenopt1=1ms +timelenopt2=1s +timelenopt3=1m +timelenopt4=1h +doubleopt=0.1 +sockaddropt=1.2.3.4:1234 +boolopt=true +boolflag1=true +boolflag2=false +boolflag3=true +deny=0.0.0.0/0 +permit=1.2.3.4/32 +codecopt=!all,ulaw,g729 +stropt=test +customopt=yes + +[global_defaults] + +[item] +intopt=-1 +uintopt=1 +timelenopt1=1 +timelenopt2=1 +timelenopt3=1 +timelenopt4=1 +doubleopt=0.1 +sockaddropt=1.2.3.4:1234 +boolopt=true +boolflag1=true +boolflag2=false +boolflag3=true +acldenyopt=0.0.0.0/0 +aclpermitopt=1.2.3.4/32 +codecopt=!all,ulaw,g729 +stropt=test +customopt=yes + +[item_defaults] diff --git a/mount/asterisk/conf/console.conf b/mount/asterisk/conf/console.conf new file mode 100644 index 0000000..aad306e --- /dev/null +++ b/mount/asterisk/conf/console.conf @@ -0,0 +1,97 @@ +; +; Configuration for chan_console, a cross-platform console channel driver. +; + +[general] + +; Set this option to "yes" to enable automatically answering calls on the +; console. This is very useful if the console is used as an intercom. +; The default value is "no". +; +;autoanswer = no + +; Set the default context to use for outgoing calls. This can be overridden by +; dialing some extension@context, unless the overridecontext option is enabled. +; The default is "default". +; +;context = default + +; Set the default extension to use for outgoing calls. The default is "s". +; +;extension = s + +; Set the default CallerID for created channels. +; +;callerid = MyName Here <(256) 428-6000> + +; Set the default language for created channels. +; +;language = en + +; If you set overridecontext to 'yes', then the whole dial string +; will be interpreted as an extension, which is extremely useful +; to dial SIP, IAX and other extensions which use the '@' character. +; The default is "no". +; +;overridecontext = no ; if 'no', the last @ will start the context + ; if 'yes' the whole string is an extension. + + +; Default Music on Hold class to use when this channel is placed on hold in +; the case that the music class is not set on the channel with +; Set(CHANNEL(musicclass)=whatever) in the dialplan and the peer channel +; putting this one on hold did not suggest a class to use. +; +;mohinterpret=default + +; ----------------------------- JITTER BUFFER CONFIGURATION -------------------------- +; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of an + ; Console channel. Defaults to "no". An enabled jitterbuffer will + ; be used only if the sending side can create and the receiving + ; side can not accept jitter. The Console channel can't accept jitter, + ; thus an enabled jitterbuffer on the receive Console side will always + ; be used if the sending side can create jitter. + +; jbmaxsize = 200 ; Max length of the jitterbuffer in milliseconds. + +; jbresyncthreshold = 1000 ; Jump in the frame timestamps over which the jitterbuffer is + ; resynchronized. Useful to improve the quality of the voice, with + ; big jumps in/broken timestamps, usually sent from exotic devices + ; and programs. Defaults to 1000. + +; jbimpl = fixed ; Jitterbuffer implementation, used on the receiving side of a Console + ; channel. Two implementations are currently available - "fixed" + ; (with size always equals to jbmax-size) and "adaptive" (with + ; variable size, actually the new jb of IAX2). Defaults to fixed. + +; jbtargetextra = 40 ; This option only affects the jb when 'jbimpl = adaptive' is set. + ; The option represents the number of milliseconds by which the new + ; jitter buffer will pad its size. the default is 40, so without + ; modification, the new jitter buffer will set its size to the jitter + ; value plus 40 milliseconds. increasing this value may help if your + ; network normally has low jitter, but occasionally has spikes. + +; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". +; ---------------------------------------------------------------------------------- + + +; +; Any configuration context defined beyond the [general] section configures +; specific devices for use. +; + +[default] +input_device = default ; When configuring an input device and output device, +output_device = default ; use the name that you see when you run the "console + ; list available" CLI command. If you say "default", the + ; system default input and output devices will be used. +autoanswer = no +context = default +extension = s +callerid = MyName Here <(256) 428-6000> +language = en +overridecontext = no +mohinterpret = default +active = yes ; This option should only be set for one console. + ; It means that it is the active console to be + ; used from the Asterisk CLI. diff --git a/mount/asterisk/conf/dbsep.conf b/mount/asterisk/conf/dbsep.conf new file mode 100644 index 0000000..7a68850 --- /dev/null +++ b/mount/asterisk/conf/dbsep.conf @@ -0,0 +1,34 @@ +# +# Configuration file for dbsep.cgi +# +# The purpose of this file is to provide realtime access to a database, +# possibly through ODBC, without needing to load the ODBC drivers into +# Asterisk, since there are several backend drivers which are rather +# buggy. +# +# We accomplish this separation by using the res_config_curl realtime +# driver to connect to a server running dbsep.cgi (or another, which +# implements the same protocol). +# +# This file contains the information necessary to configure dbsep.cgi. +# +# +# Once installed to a web server, you'll need to preload func_curl.so +# and res_config_curl.so in modules.conf and configure extconfig.conf: +# +# voicemail => curl,http://server/path/to/dbsep.cgi/voicemail +# sippeers => curl,http://server/path/to/dbsep.cgi/sippeers +# + +# The Data Source Name, as specified by the Perl DBI module. +# Typically, this will be along the lines of 'DBI:mysql:astdbname[:dbhostname]' or 'DBI:Pg:dbname=astdbname;hostname=dbhostname' +dsn=somedsn + +# Connected database user +dbuser=someuser + +# And its password +dbpass=password + +# For most databases, this is fine. Set to 'no' for Sybase or MS SQL Server. +backslash_is_escape=yes diff --git a/mount/asterisk/conf/dnsmgr.conf b/mount/asterisk/conf/dnsmgr.conf new file mode 100644 index 0000000..e34dbcf --- /dev/null +++ b/mount/asterisk/conf/dnsmgr.conf @@ -0,0 +1,5 @@ +[general] +;enable=yes ; enable creation of managed DNS lookups + ; default is 'no' +;refreshinterval=1200 ; refresh managed DNS lookups every seconds + ; default is 300 (5 minutes) \ No newline at end of file diff --git a/mount/asterisk/conf/dsp.conf b/mount/asterisk/conf/dsp.conf new file mode 100644 index 0000000..f13ca2f --- /dev/null +++ b/mount/asterisk/conf/dsp.conf @@ -0,0 +1,42 @@ +[default] +; +; Length of sound (in milliseconds) before a period of silence is considered +; to be a change from talking to silence or a period of noise converts silence +; to talking. [default=256] +; +;silencethreshold=256 + +; DTMF Reverse Twist and Normal Twist is the difference in power between the row and column energies. +; +; Normal Twist is where the row energy is greater than the column energy. +; Reverse Twist is where the column energy is greater. +; +; Power level difference between frequencies for different Administrations/RPOAs +; Power Gain equiv +; normal reverse dB's +; AT&T(default) 6.31 2.51 8dB(normal), 4dB(reverse) +; NTT 3.16 3.16 Max. 5dB +; Danish 3.98 3.98 Max. 6dB +; Australian 10.0 10.0 Max. 10dB +; Brazilian 7.94 7.94 Max. 9dB +; ETSI 3.98 3.98 Max. 6dB + +;previous version compatible AT&T values +; RADIO_RELAX disabled, and relaxdtmf=no +; 6.30 2.50 7.99dB(normal), 3.98dB(reverse) +; RADIO_RELAX disabled, and relaxdtmf=yes +; 6.30 4.00 7.99dB(normal), 6.02dB(reverse) +; RADIO_RELAX enabled, and relaxdtmf=no +; 6.30 2.50 7.99dB(normal), 3.984dB(reverse) +; RADIO_RELAX enabled, and relaxdtmf=yes +; 6.30 6.50 7.99dB(normal), 8.13dB(reverse) + +;If you don't know what these mean, don't change them. +;dtmf_normal_twist=6.31 +;dtmf_reverse_twist=2.51 +;relax_dtmf_normal_twist=6.31 +;relax_dtmf_reverse_twist=3.98 + +;successive number hits/misses of 12.75ms before a digit/nodigit is considered valid +;dtmf_hits_to_begin=2 +;dtmf_misses_to_end=3 diff --git a/mount/asterisk/conf/dundi.conf b/mount/asterisk/conf/dundi.conf new file mode 100644 index 0000000..3c67164 --- /dev/null +++ b/mount/asterisk/conf/dundi.conf @@ -0,0 +1,277 @@ +; +; DUNDi configuration file +; +; For more information about DUNDi, see http://www.dundi.com +; +; +[general] +; +; The "general" section contains general parameters relating +; to the operation of the dundi client and server. +; +; The first part should be your complete contact information +; should someone else in your peer group need to contact you. +; +;department=Your Department +;organization=Your Company, Inc. +;locality=Your City +;stateprov=ST +;country=US +;email=your@email.com +;phone=+12565551212 +; +; +; Specify bind address. IPv6 addresses are accepted. Default is 0.0.0.0 +; You can specify 'bindaddr2' to bind to another address however +; 'bindaddr and 'bindaddr2' need to be different IP protocols. +; Specify port number. Default is 4520. +; +;bindaddr=0.0.0.0 +;port=4520 +; +; See https://wiki.asterisk.org/wiki/display/AST/IP+Quality+of+Service for a description of the tos parameter. +;tos=ef +; +; Our entity identifier. (It should generally be the MAC address of the +; machine it's running on. Defaults to the first eth address, but you +; can override it here, as long as you set it to the MAC of *something* +; you own!) The EID can be overridden by a setting in asterisk.conf +; or by setting this option. +; +;entityid=00:07:E9:3B:76:60 +; +; Peers shall cache our query responses for the specified time +; in seconds. Default is 3600. +; +;cachetime=3600 +; +; This defines the max depth (hops) in which to search the DUNDi system. +; Note that the maximum time that we will wait for a response is +; (2000 + 200 * ttl) ms. +; +ttl=32 +; +; If we don't get ACK to our DPDISCOVER within 2000ms and autokill is set +; to yes then we cancel the whole thing (that's enough time for one +; retransmission only). This is used to keep things from stalling for a long +; time for a host that is not available, but would be ill advised for bad +; connections. In addition to 'yes' or 'no' you can also specify a number +; of milliseconds. See 'qualify' for individual peers to turn on for just +; a specific peer. +; +autokill=yes +; +; pbx_dundi creates a rotating key called "secret", under the family +; 'secretpath'. The default family is dundi (resulting in +; the key being held at dundi/secret). +; +;secretpath=dundi +; +; The 'storehistory' option (also changeable at runtime with +; 'dundi store history on' and 'dundi store history off') will +; cause the DUNDi engine to keep track of the last several +; queries and the amount of time each query took to execute +; for the purpose of tracking slow nodes. This option is +; off by default due to performance impacts. +; +;storehistory=yes + +[mappings] +; +; The "mappings" section maps DUNDi contexts +; to contexts on the local asterisk system. Remember +; that numbers that are made available under the e164 +; DUNDi context are regulated by the DUNDi General Peering +; Agreement (GPA) if you are a member of the DUNDi E.164 +; Peering System. +; +; dundi_context => [local_context,weight,tech,dest{,options}] +; +; 'dundi_context' is the name of the context being requested +; within the DUNDi request +; +; 'local_context' is the name of the context on the local system +; in which numbers can be looked up for which responses shall be given. +; +; 'weight' is the weight to use for the responses provided from this +; mapping. The number must be >= 0 and < 60000. Since it is totally +; valid to receive multiple responses to a query, responses received +; with a lower weight are tried first. Note that the weight has a +; special meaning in the e164 context - see the GPA for more details. +; +; 'tech' is the technology to use (IAX2, SIP, H323) +; +; 'dest' is the Dial application's channel technology resource destination +; to supply for reaching that number. The following variables can be used +; in the destination string and will be automatically substituted: +; ${NUMBER}: The number being requested +; ${IPADDR}: The IP address to connect to +; ${SECRET}: The current IAX2 rotating secret key to be used +; +; Further options may include: +; +; nounsolicited: No unsolicited calls of any type permitted via this +; route +; nocomunsolicit: No commercial unsolicited calls permitted via +; this route +; residential: This number is known to be a residence +; commercial: This number is known to be a business +; mobile: This number is known to be a mobile phone +; nocomunsolicit: No commercial unsolicited calls permitted via +; this route +; nopartial: Do not search for partial matches +; +; There *must* exist an entry in mappings for DUNDi to respond +; to any request, although it may be empty. +; +;empty_context => +; +;e164 => dundi-e164-canonical,0,IAX2,dundi:${SECRET}@${IPADDR}/${NUMBER},nounsolicited,nocomunsolicit,nopartial +;e164 => dundi-e164-customers,100,IAX2,dundi:${SECRET}@${IPADDR}/${NUMBER},nounsolicited,nocomunsolicit,nopartial +;e164 => dundi-e164-via-pstn,400,IAX2,dundi:${SECRET}@${IPADDR}/${NUMBER},nounsolicited,nocomunsolicit,nopartial +; +;digexten => default,0,IAX2,guest@lappy/${NUMBER} + +; +; Weights for mappings can be set a few different ways: +; +; 1) It can be set as a static number. +;testmap1 => context1,222,IAX2,guest@peer1/${NUMBER} +; +; 2) It can be an Asterisk global variable. +;testmap2 => context2,${DUNDITESTVAR},IAX2,guest@peer2${NUMBER} +; +; 3) It can be retrieved using a dialplan function. This can be extremely +; useful if you want to let an external script decide what the weight +; in a response should be. +;testmap3 => context3,${SHELL(echo 123)},IAX2,guest@peer3/${NUMBER} +; +; The built in variables ${SECRET}, ${IPADDR} and ${NUMBER} can also be +; passed to the weight. For example, you could pass the ${NUMBER} value +; to your SHELL() script and use that to dynamically return a weight. +; +; Note when using a global variable or dialplan function to set the +; weight for a mapping that response caching should be disabled if you +; plan for these values to change frequently at all. If the results are +; cached then any change in value will not take effect until the cache +; has expired. +; + +; +; The remaining sections represent the peers that we fundamentally trust. +; The section name specifies the peer's entityid. You can specify which +; DUNDi contexts with which you want the trust to be established. +; +; inkey - What key they will be authenticating to us with +; +; outkey - What key we use to authenticate to them +; +; host - What their host is (DNS name, IP address, or dynamic) +; +; port - The port where their host is listening (default: 4520) +; +; ustothem - Explicitly specify the entityid we use with this peer. +; +; order - What search order to use. May be 'primary', 'secondary', +; 'tertiary' or 'quartiary'. In large systems, it is beneficial +; to only query one up-stream host in order to maximize caching +; value. Adding one with primary and one with secondary gives you +; redundancy without sacrificing performance. +; +; include - Includes this peer when searching a particular context +; for lookup (set "all" to perform all lookups with that +; host. This is also the context in which peers are permitted +; to precache. +; +; noinclude - Disincludes this peer when searching a particular context +; for lookup (set "all" to perform no lookups with that +; host. +; +; permit - Permits this peer to search a given DUNDi context on +; the local system. Set "all" to permit this host to +; lookup all contexts. This is also a context for which +; we will create/forward PRECACHE commands. +; +; deny - Denies this peer to search a given DUNDi context on +; the local system. Set "all" to deny this host to +; lookup all contexts. +; +; model - inbound, outbound, or symmetric for whether we receive +; requests only, transmit requests only, or do both. +; +; precache - Utilize/Permit precaching with this peer (to pre +; cache means to provide an answer when no request +; was made and is used so that machines with few +; routes can push those routes up to a higher level). +; outgoing means we send precache routes to this peer, +; incoming means we permit this peer to send us +; precache routes. symmetric means we do both. +; +; Note: You cannot mix symmetric/outbound model with symmetric/inbound +; precache, nor can you mix symmetric/inbound model with symmetric/outbound +; precache. +; +; qualify - Enable qualifying the peer to determine reachable status. +; Set to yes, no, or number of milliseconds for qualifying +; the peer's reachable status. +; +; register - Enable registering with the peer. This presupposes that the +; peer's host option for us is dynamic. (yes/no value) +; +; The '*' peer is special and matches an unspecified entity +; + +; +; Sample Primary e164 DUNDi peer +; +;[00:50:8B:F3:75:BB] +;model = symmetric +;host = 64.215.96.114 +;inkey = digium +;outkey = misery +;include = e164 +;permit = e164 +;qualify = yes + +; +; Sample Secondary e164 DUNDi peer +; +;[00:A0:C9:96:92:84] +;model = symmetric +;host = misery.digium.com +;inkey = misery +;outkey = ourkey +;include = e164 +;permit = e164 +;qualify = yes +;order = secondary + +; +; Sample "push mode" downstream host +; +;[00:0C:76:96:75:28] +;model = inbound +;host = dynamic +;precache = inbound +;inkey = littleguy +;outkey = ourkey +;include = e164 ; In this case used only for precaching +;permit = e164 +;qualify = yes + +; +; Sample "push mode" upstream host +; +;[00:07:E9:3B:76:60] +;model = outbound +;precache = outbound +;host = 216.207.245.34 +;register = yes +;inkey = dhcp34 +;permit = all ; In this case used only for precaching +;include = all +;qualify = yes +;outkey=foo + +;[*] +; diff --git a/mount/asterisk/conf/enum.conf b/mount/asterisk/conf/enum.conf new file mode 100644 index 0000000..39c7231 --- /dev/null +++ b/mount/asterisk/conf/enum.conf @@ -0,0 +1,22 @@ +; +; ENUM Configuration for resolving phone numbers over DNS +; +; Sample config for Asterisk +; This file is reloaded at "module reload enum" in the CLI +; +[general] +; +; The search list for domains may be customized. Domains are searched +; in the order they are listed here. +; +search => e164.arpa +; +; If you'd like to use the E.164.org public ENUM registry in addition +; to the official e164.arpa one, uncomment the following line +; +;search => e164.org +; +; As there are more H323 drivers available you have to select to which +; drive a H323 URI will map. Default is "H323". +; +h323driver => H323 diff --git a/mount/asterisk/conf/extconfig.conf b/mount/asterisk/conf/extconfig.conf new file mode 100644 index 0000000..b633faf --- /dev/null +++ b/mount/asterisk/conf/extconfig.conf @@ -0,0 +1,112 @@ +; +; Static and realtime external configuration +; engine configuration +; +; See https://wiki.asterisk.org/wiki/display/AST/Realtime+Database+Configuration +; for basic table formatting information. +; +[settings] +; +; Static configuration files: +; +; file.conf => driver,database[,table[,priority]] +; +; maps a particular configuration file to the given +; database driver, database and table (or uses the +; name of the file as the table if not specified) +; +; Uncomment to load queues.conf via the odbc engine. +; +;queues.conf => odbc,asterisk,ast_config +;extensions.conf => sqlite,asterisk,ast_config +; +; The following files CANNOT be loaded from Realtime storage: +; asterisk.conf +; extconfig.conf (this file) +; logger.conf +; +; Additionally, the following files cannot be loaded from +; Realtime storage unless the storage driver is loaded +; early using 'preload' statements in modules.conf: +; manager.conf +; cdr.conf +; rtp.conf +; +; Named ACLs specified in realtime also can not be used +; from manager.conf unless the storage driver is preloaded. +; Attempting to use a realtime stored named ACL before the +; driver is loaded will result in an invalid ACL which +; rejects all addresses. +; +; Realtime configuration engine +; +; maps a particular family of realtime +; configuration to a given database driver, +; database and table (or uses the name of +; the family if the table is not specified +; +;example => odbc,asterisk,alttable,1 +;example => mysql,asterisk,alttable,2 +;example2 => ldap,"dc=oxymium,dc=net",example2 +; +; Additionally, priorities are now supported for use as failover methods +; for retrieving realtime data. If one connection fails to retrieve any +; information, the next sequential priority will be tried next. This +; especially works well with ODBC connections, since res_odbc now caches +; when connection failures occur and prevents immediately retrying those +; connections until after a specified timeout. Note: priorities must +; start at 1 and be sequential (i.e. if you have only priorities 1, 2, +; and 4, then 4 will be ignored, because there is no 3). +; +; +; Possible driver backends: +; +; "odbc" is shown in the examples below, but is not the only valid realtime +; engine. Here are several of the possible options: +; odbc ... res_config_odbc +; sqlite ... res_config_sqlite +; sqlite3 ... res_config_sqlite3 +; pgsql ... res_config_pgsql +; curl ... res_config_curl +; ldap ... res_config_ldap +; mysql ... res_config_mysql (available via add-ons in menuselect) +; +; Note: The res_config_pgsql and res_config_sqlite backends configure the +; database used in their respective configuration files and ignore the +; database name configured in this file. +; +;iaxusers => odbc,asterisk +;iaxpeers => odbc,asterisk +;sippeers => odbc,asterisk +;sipregs => odbc,asterisk ; (avoid sipregs if possible, e.g. by using a view) +;ps_endpoints => odbc,asterisk +;ps_auths => odbc,asterisk +;ps_aors => odbc,asterisk +;ps_domain_aliases => odbc,asterisk +;ps_endpoint_id_ips => odbc,asterisk +;ps_outbound_publishes => odbc,asterisk +;ps_inbound_publications = odbc,asterisk +;ps_asterisk_publications = odbc,asterisk +;voicemail => odbc,asterisk +;extensions => odbc,asterisk +;meetme => mysql,general +;queues => odbc,asterisk +;queue_members => odbc,asterisk +;queue_rules => odbc,asterisk +;acls => odbc,asterisk +;musiconhold => mysql,general +;musiconhold_entry => mysql,general +;queue_log => mysql,general +; +; +; While most dynamic realtime engines are automatically used when defined in +; this file, 'extensions', distinctively, is not. To activate dynamic realtime +; extensions, you must turn them on in each respective context within +; extensions.conf with a switch statement. The syntax is: +; switch => Realtime/[[db_context@]tablename]/ +; The only option available currently is the 'p' option, which disallows +; extension pattern queries to the database. If you have no patterns defined +; in a particular context, this will save quite a bit of CPU time. However, +; note that using dynamic realtime extensions is not recommended anymore as a +; best practice; instead, you should consider writing a static dialplan with +; proper data abstraction via a tool like func_odbc. diff --git a/mount/asterisk/conf/extensions.ael b/mount/asterisk/conf/extensions.ael new file mode 100644 index 0000000..495001f --- /dev/null +++ b/mount/asterisk/conf/extensions.ael @@ -0,0 +1,456 @@ +// +// Example AEL config file +// +// +// Static extension configuration file, used by +// the pbx_ael module. This is where you configure all your +// inbound and outbound calls in Asterisk. +// +// This configuration file is reloaded +// - With the "ael reload" command in the CLI +// - With the "reload" command (that reloads everything) in the CLI + +// The "Globals" category contains global variables that can be referenced +// in the dialplan by using the GLOBAL dialplan function: +// ${GLOBAL(VARIABLE)} +// ${${GLOBAL(VARIABLE)}} or ${text${GLOBAL(VARIABLE)}} or any hybrid +// Unix/Linux environmental variables are reached with the ENV dialplan +// function: ${ENV(VARIABLE)} +// + +// NOTE! NOTE! NOTE! +// Asterisk by default will load both extensions.conf and extensions.ael files. +// Upon loading these files the dialplans generated from both with be merged, +// so you must make sure that you don't have any overlapping contexts or global +// variables. If you do, then unexpected behavior may result when the data is +// merged. +// NOTE! NOTE! NOTE! + +globals { + CONSOLE-AEL="Console/dsp"; // Console interface for demo + //CONSOLE-AEL=Zap/1; + //CONSOLE-AEL=Phone/phone0; + IAXINFO-AEL=guest; // IAXtel username/password + //IAXINFO-AEL="myuser:mypass"; + OUTBOUND-TRUNK="Zap/g2"; // Trunk interface + // + // Note the 'g2' in the OUTBOUND-TRUNK variable above. It specifies which group (defined + // in chan_dahdi.conf) to dial, i.e. group 2, and how to choose a channel to use in + // the specified group. The four possible options are: + // + // g: select the lowest-numbered non-busy DAHDI channel + // (aka. ascending sequential hunt group). + // G: select the highest-numbered non-busy DAHDI channel + // (aka. descending sequential hunt group). + // r: use a round-robin search, starting at the next highest channel than last + // time (aka. ascending rotary hunt group). + // R: use a round-robin search, starting at the next lowest channel than last + // time (aka. descending rotary hunt group). + // + OUTBOUND-TRUNKMSD=1; // MSD digits to strip (usually 1 or 0) + //OUTBOUND-TRUNK2=IAX2/user:pass@provider; +}; + +// +// Any category other than "General" and "Globals" represent +// extension contexts, which are collections of extensions. +// +// Extension names may be numbers, letters, or combinations +// thereof. If an extension name is prefixed by a '_' +// character, it is interpreted as a pattern rather than a +// literal. In patterns, some characters have special meanings: +// +// X - any digit from 0-9 +// Z - any digit from 1-9 +// N - any digit from 2-9 +// [1235-9] - any digit in the brackets (in this example, 1,2,3,5,6,7,8,9) +// . - wildcard, matches anything remaining (e.g. _9011. matches +// anything starting with 9011 excluding 9011 itself) +// ! - wildcard, causes the matching process to complete as soon as +// it can unambiguously determine that no other matches are possible +// +// For example the extension _NXXXXXX would match normal 7 digit dialings, +// while _1NXXNXXXXXX would represent an area code plus phone number +// preceded by a one. +// +// Each step of an extension is ordered by priority, which must +// always start with 1 to be considered a valid extension. The priority +// "next" or "n" means the previous priority plus one, regardless of whether +// the previous priority was associated with the current extension or not. +// The priority "same" or "s" means the same as the previously specified +// priority, again regardless of whether the previous entry was for the +// same extension. Priorities may be immediately followed by a plus sign +// and another integer to add that amount (most useful with 's' or 'n'). +// Priorities may then also have an alias, or label, in +// parenthesis after their name which can be used in goto situations +// +// Contexts contain several lines, one for each step of each +// extension, which can take one of two forms as listed below, +// with the first form being preferred. One may include another +// context in the current one as well, optionally with a +// date and time. Included contexts are included in the order +// they are listed. +// +//context name { +// exten-name => { +// application(arg1,arg2,...); +// +// Timing list for includes is +// +//