From f14a2f1ed6852455240fb9b54d62d03422865dfd Mon Sep 17 00:00:00 2001 From: Tyler Moore Date: Thu, 1 Jul 2021 12:25:12 -0400 Subject: [PATCH] Improved DNS Hostname Resolution And Caching Resolves https://github.com/dOpensource/dsiprouter/issues/325 - implement new caching system via cronjob - update dr_gateways DNS names to resolve to all available IP's - update uacreg DNS names to resolve to all available IP's - update DNS names every 5 minutes - update backend to transparently access/store JSON in description/tag fields - update all other tables to use new schema for JSON storage - move local address to cron updated entry in address table - add FLT_INTERNAL flag for internal use addresses - add/update a few utility functions to `dsip_lib.sh` - update default imports to use new JSON structure --- CHANGELOG.md | 27 ++ dsiprouter.sh | 228 ++++++++++++-- dsiprouter/dsip_lib.sh | 56 +++- gui/database/__init__.py | 252 ++++++++++++--- gui/dsiprouter.py | 178 +++++------ gui/modules/api/api_routes.py | 290 ++++++++++-------- .../dnid_enrichment/dnid_enrichment.sql | 2 +- gui/modules/dnid_enrichment/install.sh | 4 +- gui/modules/domain/domain_routes.py | 4 +- gui/settings.py | 5 +- gui/shared.py | 9 +- gui/util/networking.py | 18 +- kamailio/defaults/address.csv | 149 ++++----- kamailio/defaults/address.sql | 3 +- kamailio/defaults/carrierfailureroute.sql | 4 + kamailio/defaults/carrierroute.sql | 4 + kamailio/defaults/dispatcher.sql | 2 +- kamailio/defaults/domainpolicy.sql | 4 + kamailio/defaults/dr_gateways.csv | 106 +++---- kamailio/defaults/dr_gateways.sql | 3 +- kamailio/defaults/dr_groups.sql | 4 + kamailio/defaults/dr_gw_lists.csv | 20 +- kamailio/defaults/dr_gw_lists.sql | 3 +- kamailio/defaults/dr_rules.csv | 2 +- kamailio/defaults/dr_rules.sql | 3 +- kamailio/defaults/globalblacklist.sql | 4 + kamailio/defaults/lcr_gw.sql | 4 + kamailio/defaults/speed_dial.sql | 4 + kamailio/defaults/trusted.sql | 4 + kamailio/kamailio_dsiprouter.cfg | 3 +- 30 files changed, 955 insertions(+), 444 deletions(-) create mode 100644 kamailio/defaults/carrierfailureroute.sql create mode 100644 kamailio/defaults/carrierroute.sql create mode 100644 kamailio/defaults/domainpolicy.sql create mode 100644 kamailio/defaults/dr_groups.sql create mode 100644 kamailio/defaults/globalblacklist.sql create mode 100644 kamailio/defaults/lcr_gw.sql create mode 100644 kamailio/defaults/speed_dial.sql create mode 100644 kamailio/defaults/trusted.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index 17e274c3..1f7d70c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ [//]: # (END_SECTION HEADER) [//]: # (START_SECTION COMMITS +7287564593dd788bdfc5e3472cca0bd89b84a4bc d8ac84aa08a89a604320df81870c18c734f8fdf0 3893533afbfaf9d5aedb02b45688ac94920cbd4f f8bfe45b3cc64e49d3decc0adb7a10f493ff22a0 @@ -1969,6 +1970,32 @@ a72121b9551921aa3dced32d943c6034ba318f82 ce6c5aac0db5476dc496c34388e4f9ce2c4b86e5 b46b1e64f06f448bde78b98e3ae8228ce5f96067 END_SECTION COMMITS) +[//]: # (START_SECTION 7287564593dd788bdfc5e3472cca0bd89b84a4bc) +### Improved DNS Hostname Resolution And Caching + +> Commit: [7287564593dd788bdfc5e3472cca0bd89b84a4bc](https://github.com/dOpensource/dsiprouter/commit/7287564593dd788bdfc5e3472cca0bd89b84a4bc) +> Date: Thu, 1 Jul 2021 12:25:12 -0400 +> Author: Tyler Moore (tmoore@goflyball.com) +> Committer: Tyler Moore (tmoore@goflyball.com) +> Signed: Tyler Moore (devopsec) + + +- Resolves [#325](https://github.com/dOpensource/dsiprouter/issues/325) +- implement new caching system via cronjob +- update dr_gateways DNS names to resolve to all available IP's +- update uacreg DNS names to resolve to all available IP's +- update DNS names every 5 minutes +- update backend to transparently access/store JSON in description/tag fields +- update all other tables to use new schema for JSON storage +- move local address to cron updated entry in address table +- add FLT_INTERNAL flag for internal use addresses +- add/update a few utility functions to `dsip_lib.sh` +- update default imports to use new JSON structure + + +--- + +[//]: # (END_SECTION 7287564593dd788bdfc5e3472cca0bd89b84a4bc) [//]: # (START_SECTION d8ac84aa08a89a604320df81870c18c734f8fdf0) ### Fix Bug In Commit 9e7949a diff --git a/dsiprouter.sh b/dsiprouter.sh index 36589b29..58d7fc9d 100755 --- a/dsiprouter.sh +++ b/dsiprouter.sh @@ -67,6 +67,7 @@ setStaticScriptSettings() { FLT_CARRIER=8 FLT_PBX=9 FLT_MSTEAMS=22 + FLT_INTERNAL=20 FLT_OUTBOUND=8000 FLT_INBOUND=9000 FLT_LCR_MIN=10000 @@ -514,6 +515,14 @@ export -f reconfigureMysqlSystemdService # generate dynamic python config settings on install function configurePythonSettings { + setConfigAttrib 'FLT_CARRIER' "$FLT_CARRIER" ${DSIP_CONFIG_FILE} + setConfigAttrib 'FLT_PBX' "$FLT_PBX" ${DSIP_CONFIG_FILE} + setConfigAttrib 'FLT_MSTEAMS' "$FLT_MSTEAMS" ${DSIP_CONFIG_FILE} + setConfigAttrib 'FLT_INTERNAL' "$FLT_INTERNAL" ${DSIP_CONFIG_FILE} + setConfigAttrib 'FLT_OUTBOUND' "$FLT_OUTBOUND" ${DSIP_CONFIG_FILE} + setConfigAttrib 'FLT_INBOUND' "$FLT_INBOUND" ${DSIP_CONFIG_FILE} + setConfigAttrib 'FLT_LCR_MIN' "$FLT_LCR_MIN" ${DSIP_CONFIG_FILE} + setConfigAttrib 'FLT_FWD_MIN' "$FLT_FWD_MIN" ${DSIP_CONFIG_FILE} setConfigAttrib 'KAM_KAMCMD_PATH' "$(type -p kamcmd)" ${DSIP_CONFIG_FILE} -q setConfigAttrib 'KAM_CFG_PATH' "$SYSTEM_KAMAILIO_CONFIG_FILE" ${DSIP_CONFIG_FILE} -q setConfigAttrib 'RTP_CFG_PATH' "$SYSTEM_RTPENGINE_CONFIG_FILE" ${DSIP_CONFIG_FILE} -q @@ -649,19 +658,19 @@ function updateKamailioConfig { # update kamailio config file if (( $DEBUG == 1 )); then - enableKamailioConfigAttrib 'WITH_DEBUG' ${DSIP_KAMAILIO_CONFIG_FILE} + enableKamailioConfigFeature 'WITH_DEBUG' ${DSIP_KAMAILIO_CONFIG_FILE} else - disableKamailioConfigAttrib 'WITH_DEBUG' ${DSIP_KAMAILIO_CONFIG_FILE} + disableKamailioConfigFeature 'WITH_DEBUG' ${DSIP_KAMAILIO_CONFIG_FILE} fi if (( $SERVERNAT == 1 )); then - enableKamailioConfigAttrib 'WITH_SERVERNAT' ${DSIP_KAMAILIO_CONFIG_FILE} + enableKamailioConfigFeature 'WITH_SERVERNAT' ${DSIP_KAMAILIO_CONFIG_FILE} else - disableKamailioConfigAttrib 'WITH_SERVERNAT' ${DSIP_KAMAILIO_CONFIG_FILE} + disableKamailioConfigFeature 'WITH_SERVERNAT' ${DSIP_KAMAILIO_CONFIG_FILE} fi if [[ -n "$KAM_HOMER_HOST" ]]; then - enableKamailioConfigAttrib 'WITH_HOMER' ${DSIP_KAMAILIO_CONFIG_FILE} + enableKamailioConfigFeature 'WITH_HOMER' ${DSIP_KAMAILIO_CONFIG_FILE} else - disableKamailioConfigAttrib 'WITH_HOMER' ${DSIP_KAMAILIO_CONFIG_FILE} + enableKamailioConfigFeature 'WITH_HOMER' ${DSIP_KAMAILIO_CONFIG_FILE} fi setKamailioConfigSubstdef 'DSIP_ID' "${DSIP_ID}" ${DSIP_KAMAILIO_CONFIG_FILE} setKamailioConfigSubstdef 'DSIP_VERSION' "${DSIP_VERSION}" ${DSIP_KAMAILIO_CONFIG_FILE} @@ -675,6 +684,14 @@ function updateKamailioConfig { setKamailioConfigSubstdef 'DMQ_PORT' "${KAM_DMQ_PORT}" ${DSIP_KAMAILIO_CONFIG_FILE} setKamailioConfigSubstdef 'HEP_PORT' "${KAM_HEP_PORT}" ${DSIP_KAMAILIO_CONFIG_FILE} setKamailioConfigSubstdef 'HOMER_HOST' "${KAM_HOMER_HOST}" ${DSIP_KAMAILIO_CONFIG_FILE} + setKamailioConfigDef 'FLT_CARRIER' "$FLT_CARRIER" ${DSIP_KAMAILIO_CONFIG_FILE} + setKamailioConfigDef 'FLT_PBX' "$FLT_PBX" ${DSIP_KAMAILIO_CONFIG_FILE} + setKamailioConfigDef 'FLT_MSTEAMS' "$FLT_MSTEAMS" ${DSIP_KAMAILIO_CONFIG_FILE} + setKamailioConfigDef 'FLT_INTERNAL' "$FLT_INTERNAL" ${DSIP_KAMAILIO_CONFIG_FILE} + setKamailioConfigDef 'FLT_OUTBOUND' "$FLT_OUTBOUND" ${DSIP_KAMAILIO_CONFIG_FILE} + setKamailioConfigDef 'FLT_INBOUND' "$FLT_INBOUND" ${DSIP_KAMAILIO_CONFIG_FILE} + setKamailioConfigDef 'FLT_LCR_MIN' "$FLT_LCR_MIN" ${DSIP_KAMAILIO_CONFIG_FILE} + setKamailioConfigDef 'FLT_FWD_MIN' "$FLT_FWD_MIN" ${DSIP_KAMAILIO_CONFIG_FILE} setKamailioConfigGlobal 'server.api_server' "${DSIP_API_BASEURL}" ${DSIP_KAMAILIO_CONFIG_FILE} setKamailioConfigGlobal 'server.api_token' "${DSIP_API_TOKEN}" ${DSIP_KAMAILIO_CONFIG_FILE} setKamailioConfigGlobal 'server.role' "${ROLE}" ${DSIP_KAMAILIO_CONFIG_FILE} @@ -700,7 +717,7 @@ function updateKamailioConfig { # note: the '@' symbol must be escaped in perl regex if printf '%s' "$KAM_DB_HOST" | grep -q -oP '(\[.*\]|.*,.*)'; then # db connection is clustered - enableKamailioConfigAttrib 'WITH_DBCLUSTER' ${DSIP_KAMAILIO_CONFIG_FILE} + enableKamailioConfigFeature 'WITH_DBCLUSTER' ${DSIP_KAMAILIO_CONFIG_FILE} # TODO: support different type/user/pass/port/name per connection # TODO: support multiple clusters @@ -837,6 +854,121 @@ function updateCACertsDir { chmod 640 ${DSIP_CERTS_DIR}/ca/cert.*.pem } +# Update dynamic addresses in address table +function updateDynamicAddresses { + local OLD_ADDR_IDS=( ) NEW_ADDR_IDS=( ) NEW_ADDR_LIST=( ) SQL_STATEMENTS=( ) + lcaol OLD_ADDR_ID="" UAC_ID="" SIP_ADDR="" INSERT_TEMPLATE="" + + # update resolved IP address entries for dr_gateways entries using DNS addresses + # - dr_gateways to address mapping: dr_gateways.description['addr_list'] -> address.id + while IFS= read -r ROW; do + # split up the fields + OLD_ADDR_IDS=( $(cut -d $'\t' -f 1 <<<"$ROW") ) + SIP_ADDR=$(cut -d $'\t' -f 2 <<<"$ROW") + + # get other address fields (should be same for the list of addresses) + INSERT_TEMPLATE=$( + mysql -sNA --user="$KAM_DB_USER" --password="$KAM_DB_PASS" --host="$KAM_DB_HOST" --port="$KAM_DB_PORT" $KAM_DB_NAME \ + -e "SELECT * FROM address WHERE id IN (${OLD_ADDR_IDS[@]}) LIMIT 1;" | + awk -F $'\t' '{printf "INSERT INTO address VALUES(NULL,%s,RESOLVED_ADDR,%s,%s,%s);",$2,$4,$5,$6}' + ) + + # delete old addresses and create new ones + SQL_STATEMENTS+=("DELETE FROM address WHERE id IN (${OLD_ADDR_IDS[@]});") + for ADDR in $(hostToIP -a "$SIP_ADDR"); do + NEW_ADDR_LIST+=("$ADDR") + SQL_STATEMENTS+=( $(perl -e "\$addr='$ADDR';" -pe 's%RESOLVED_ADDR%${addr}%' <<<"$INSERT_TEMPLATE" 2>/dev/null) ) + done + + # run sql statements as a transaction and check for errors + sqlAsTransaction --user="$MYSQL_ROOT_USERNAME" --password="$MYSQL_ROOT_PASSWORD" --host="$KAM_DB_HOST" --port="$KAM_DB_PORT" --db="$KAM_DB_NAME" "${SQL_STATEMENTS[@]}" + (( $? != 0 )) && { printerr 'Failed updating gateway associated addresses'; cleanupAndExit 1; } + + # update address list + NEW_ADDR_IDS=( $( + mysql -sNA --user="$KAM_DB_USER" --password="$KAM_DB_PASS" --host="$KAM_DB_HOST" --port="$KAM_DB_PORT" $KAM_DB_NAME \ + -e "SELECT id FROM address WHERE ip_addr IN ($(joinwith '' ',' '' ${NEW_ADDR_LIST[@]});" + ) ) + + # run sql statements as a transaction and check for errors + sqlAsTransaction --user="$MYSQL_ROOT_USERNAME" --password="$MYSQL_ROOT_PASSWORD" --host="$KAM_DB_HOST" --port="$KAM_DB_PORT" --db="$KAM_DB_NAME" \ + "UPDATE dr_gateways SET description = JSON_REPLACE(description, '$.addr_list', '[$(joinwith '' ',' '' ${NEW_ADDR_IDS[@]})]');" + (( $? != 0 )) && { printerr 'Failed updating gateway associated addresses'; cleanupAndExit 1; } + + done < <( + mysql -sNA --user="$KAM_DB_USER" --password="$KAM_DB_PASS" --host="$KAM_DB_HOST" --port="$KAM_DB_PORT" $KAM_DB_NAME <<-'EOF' +SELECT REGEXP_REPLACE(JSON_EXTRACT(description, '$.addr_list'), '\\[([^\\[\\]]+)\\]', '\\1') AS addr_list, address AS sip_addr +FROM dr_gateways +WHERE JSON_EXISTS(description, '$.addr_list') + AND REGEXP_REPLACE(address, + '^' + '(?:(?P[a-zA-Z]+):/?/?)?' + '(?:(?P[a-zA-Z0-9\\-_.]+(?::.+)?)(?:@))?' + '(?:' + '(?:\\[?(?P(?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\\]?)|' + '(?P(?:[0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.(?:[0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.(?:[0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.(?:[0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5]))|' + '(?P(?:(?:[a-zA-Z0-9]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9])\\.)*(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9]))' + ')' + '(?::(?P[1-9]|[1-5]?[0-9]{2,4}|6[1-4][0-9]{3}|65[1-4][0-9]{2}|655[1-2][0-9]|6553[1-5]))?' + '(?P/[^\\s?;]*)?' + '(?:(?:[?;])(?P.*))?' + '$', + '\\5') <> ''; +EOF +) + + # reset vars + OLD_ADDR_IDS=( ) NEW_ADDR_IDS=( ) NEW_ADDR_LIST=( ) SQL_STATEMENTS=( ) + OLD_ADDR_ID="" UAC_ID="" SIP_ADDR="" INSERT_TEMPLATE="" + + # update resolved IP address entries for dr_gateways and uacreg entries using DNS addresses + # - dr_gateways to address mapping: dr_gateways.description['addr_list'] -> address.id + # - uacreg to address mapping: uacreg.l_uuid -> dr_gw_lists.id, dr_gw_lists.description['name']+'-uac' -> address.tag['name'] + while IFS= read -r ROW; do + # split up the fields + OLD_ADDR_ID=$(cut -d $'\t' -f 1 <<<"$ROW") + UAC_ID=$(cut -d $'\t' -f 2 <<<"$ROW") + + # get other address fields (will make new address associated to uac entry) + INSERT_TEMPLATE=$( + mysql -sNA --user="$KAM_DB_USER" --password="$KAM_DB_PASS" --host="$KAM_DB_HOST" --port="$KAM_DB_PORT" $KAM_DB_NAME \ + -e "SELECT * FROM address WHERE id='$OLD_ADDR_ID' LIMIT 1;" | + awk -F $'\t' '{printf "INSERT INTO address VALUES(NULL,%s,RESOLVED_ADDR,%s,%s,%s);",$2,$4,$5,$6}' + ) + + # delete old addresses and create new ones + SQL_STATEMENTS+=("DELETE FROM address WHERE id='$OLD_ADDR_ID';") + for ADDR in $(hostToIP -a "$SIP_ADDR"); do + NEW_ADDR_LIST+=("$ADDR") + SQL_STATEMENTS+=( $(perl -e "\$addr='$ADDR';" -pe 's%RESOLVED_ADDR%${addr}%' <<<"$INSERT_TEMPLATE" 2>/dev/null) ) + done + + # update address list + NEW_ADDR_IDS=( $( + mysql -sNA --user="$KAM_DB_USER" --password="$KAM_DB_PASS" --host="$KAM_DB_HOST" --port="$KAM_DB_PORT" $KAM_DB_NAME \ + -e "SELECT id FROM address WHERE ip_addr IN ($(joinwith '' ',' '' ${NEW_ADDR_LIST[@]});" + ) ) + done < <( + mysql -sNA --user="$KAM_DB_USER" --password="$KAM_DB_PASS" --host="$KAM_DB_HOST" --port="$KAM_DB_PORT" $KAM_DB_NAME <<-'EOF' +SELECT t1.id AS uac_id, t3.id AS addr_id +FROM uacreg t1 + JOIN dr_gw_lists t2 ON t1.l_uuid = t2.id + JOIN address t3 ON CONCAT(JSON_UNQUOTE(JSON_EXTRACT(t2.description, '$.name')), '-uac') = + JSON_UNQUOTE(JSON_EXTRACT(t3.tag, '$.name')); +EOF +) + + # run sql statements after collecting them all, as a transaction and check for errors + sqlAsTransaction --user="$MYSQL_ROOT_USERNAME" --password="$MYSQL_ROOT_PASSWORD" --host="$KAM_DB_HOST" --port="$KAM_DB_PORT" --db="$KAM_DB_NAME" "${SQL_STATEMENTS[@]}" + (( $? != 0 )) && { printerr 'Failed updating uac auth associated addresses'; cleanupAndExit 1; } + + # update local addresses that may change as network changes + local INTERNAL_NET_PREFIX=$(echo -n "$INTERNAL_NET" | cut -d '/' -f 2) + sqlAsTransaction --user="$MYSQL_ROOT_USERNAME" --password="$MYSQL_ROOT_PASSWORD" --host="$KAM_DB_HOST" --port="$KAM_DB_PORT" --db="$KAM_DB_NAME" \ + "UPDATE address set ip_addr='$INTERNAL_IP', mask='$INTERNAL_NET_PREFIX' WHERE JSON_UNQUOTE(JSON_EXTRACT(tag, '$.name')) = 'dsip-internal';" + (( $? != 0 )) && { printerr 'Failed updating internal dynamic addresses'; cleanupAndExit 1; } +} + function generateKamailioConfig { # copy of template kamailio configuration to dsiprouter system config dir cp -f ${DSIP_KAMAILIO_CONFIG_DIR}/kamailio_dsiprouter.cfg ${DSIP_KAMAILIO_CONFIG_FILE} @@ -857,9 +989,9 @@ function generateKamailioConfig { # non-module features to enable if (( ${WITH_LCR} == 1 )); then - enableKamailioConfigAttrib 'WITH_LCR' ${DSIP_KAMAILIO_CONFIG_FILE} + enableKamailioConfigFeature 'WITH_LCR' ${DSIP_KAMAILIO_CONFIG_FILE} else - disableKamailioConfigAttrib 'WITH_LCR' ${DSIP_KAMAILIO_CONFIG_FILE} + disableKamailioConfigFeature 'WITH_LCR' ${DSIP_KAMAILIO_CONFIG_FILE} fi # Backup kamcfg and link the dsiprouter kamcfg @@ -911,14 +1043,30 @@ function configureKamailioDB { mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ < ${DSIP_DEFAULTS_DIR}/address.sql + # Update schema for carrierroute table + mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ + < ${DSIP_DEFAULTS_DIR}/carrierroute.sql + + # Update schema for carrierfailureroute table + mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ + < ${DSIP_DEFAULTS_DIR}/carrierfailureroute.sql + # Update schema for dispatcher table mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ < ${DSIP_DEFAULTS_DIR}/dispatcher.sql + # Update schema for domainpolicy table + mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ + < ${DSIP_DEFAULTS_DIR}/domainpolicy.sql + # Update schema for dr_gateways table mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ < ${DSIP_DEFAULTS_DIR}/dr_gateways.sql + # Update schema for dr_groups table + mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ + < ${DSIP_DEFAULTS_DIR}/dr_groups.sql + # Update schema for dr_gw_lists table mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ < ${DSIP_DEFAULTS_DIR}/dr_gw_lists.sql @@ -927,10 +1075,26 @@ function configureKamailioDB { mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ < ${DSIP_DEFAULTS_DIR}/dr_rules.sql + # Update schema for globalblacklist table + mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ + < ${DSIP_DEFAULTS_DIR}/globalblacklist.sql + + # Update schema for lcr_gw table + mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ + < ${DSIP_DEFAULTS_DIR}/lcr_gw.sql + + # Update schema for speed_dial table + mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ + < ${DSIP_DEFAULTS_DIR}/speed_dial.sql + # Update schema for subscribers table mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ < ${DSIP_DEFAULTS_DIR}/subscriber.sql + # Update schema for trusted table + mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ + < ${DSIP_DEFAULTS_DIR}/trusted.sql + # Install schema for custom LCR logic mysql -s -N --user="$ROOT_DB_USER" --password="$ROOT_DB_PASS" --host="${KAM_DB_HOST}" --port="${KAM_DB_PORT}" $KAM_DB_NAME \ < ${DSIP_DEFAULTS_DIR}/dsip_lcr.sql @@ -995,11 +1159,12 @@ function configureKamailioDB { # import default carriers and outbound routes mkdir -p /tmp/defaults + local INTERNAL_NET_PREFIX=$(echo -n "$INTERNAL_NET" | cut -d '/' -f 2) # generate defaults subbing in dynamic values cp -f ${DSIP_DEFAULTS_DIR}/dr_gw_lists.csv /tmp/defaults/dr_gw_lists.csv - sed "s/FLT_CARRIER/$FLT_CARRIER/g; s/FLT_PBX/$FLT_PBX/g; s/FLT_MSTEAMS/$FLT_MSTEAMS/g" \ + sed "s/FLT_CARRIER/$FLT_CARRIER/g; s/FLT_PBX/$FLT_PBX/g; s/FLT_MSTEAMS/$FLT_MSTEAMS/g; s/FLT_INTERNAL/$FLT_INTERNAL/g; s/INTERNAL_IP/$INTERNAL_IP/g s/INTERNAL_NET_PREFIX/$INTERNAL_NET_PREFIX/g" \ ${DSIP_DEFAULTS_DIR}/address.csv > /tmp/defaults/address.csv - sed "s/FLT_CARRIER/$FLT_CARRIER/g; s/FLT_PBX/$FLT_PBX/g; s/FLT_MSTEAMS/$FLT_MSTEAMS/g" \ + sed "s/FLT_CARRIER/$FLT_CARRIER/g; s/FLT_PBX/$FLT_PBX/g; s/FLT_MSTEAMS/$FLT_MSTEAMS/g; s/FLT_INTERNAL/$FLT_INTERNAL/g" \ ${DSIP_DEFAULTS_DIR}/dr_gateways.csv > /tmp/defaults/dr_gateways.csv sed "s/FLT_OUTBOUND/$FLT_OUTBOUND/g; s/FLT_INBOUND/$FLT_INBOUND/g" \ ${DSIP_DEFAULTS_DIR}/dr_rules.csv > /tmp/defaults/dr_rules.csv @@ -1020,14 +1185,14 @@ function configureKamailioDB { # TODO: deprecated since CLI command is being deprecated function enableSERVERNAT { - enableKamailioConfigAttrib 'WITH_SERVERNAT' ${DSIP_KAMAILIO_CONFIG_FILE} + enableKamailioConfigFeature 'WITH_SERVERNAT' ${DSIP_KAMAILIO_CONFIG_FILE} printwarn "SERVERNAT is enabled - Restarting Kamailio is required" printwarn "You can restart it by executing: systemctl restart kamailio" } # TODO: deprecated since CLI command is being deprecated function disableSERVERNAT { - disableKamailioConfigAttrib 'WITH_SERVERNAT' ${DSIP_KAMAILIO_CONFIG_FILE} + disableKamailioConfigFeature 'WITH_SERVERNAT' ${DSIP_KAMAILIO_CONFIG_FILE} printwarn "SERVERNAT is disabled - Restarting Kamailio is required" printdbg "You can restart it by executing: systemctl restart kamailio" @@ -1117,7 +1282,7 @@ configureSystemRepos() { printerr 'Could not configure system repositories' cleanupAndExit 1 elif (( $? >= 100 )); then - printwarn 'Some issue(s) with system repositories' + printwarn 'Some issue(s) with system repositories' else printdbg 'System repositories configured successfully' touch ${DSIP_SYSTEM_CONFIG_DIR}/.reposconfigured @@ -1199,11 +1364,11 @@ function installRTPEngine { ${DSIP_PROJECT_DIR}/rtpengine/${DISTRO}/install.sh install ret=$? if (( $ret == 0 )); then - enableKamailioConfigAttrib 'WITH_RTPENGINE' ${DSIP_KAMAILIO_CONFIG_FILE} + enableKamailioConfigFeature 'WITH_RTPENGINE' ${DSIP_KAMAILIO_CONFIG_FILE} systemctl restart kamailio printdbg "configuring RTPEngine service" elif (( $ret == 2 )); then - enableKamailioConfigAttrib 'WITH_RTPENGINE' ${DSIP_KAMAILIO_CONFIG_FILE} + enableKamailioConfigFeature 'WITH_RTPENGINE' ${DSIP_KAMAILIO_CONFIG_FILE} printwarn "RTPEngine install waiting on reboot" cleanupAndExit 0 else @@ -1237,7 +1402,7 @@ function uninstallRTPEngine { if (( $? == 0 )); then if [ -f "${DSIP_SYSTEM_CONFIG_DIR}/.kamailioinstalled" ]; then - disableKamailioConfigAttrib 'WITH_RTPENGINE' ${DSIP_KAMAILIO_CONFIG_FILE} + disableKamailioConfigFeature 'WITH_RTPENGINE' ${DSIP_KAMAILIO_CONFIG_FILE} systemctl restart kamailio fi else @@ -1513,6 +1678,8 @@ function installKamailio { generateKamailioConfig updateKamailioConfig updateKamailioStartup + # update dynamic addresses every 5 minutes + cronAppend "*/5 * * * * ${DSIP_PROJECT_DIR}/dsiprouter.sh updatedynamicaddrs" else printerr "kamailio install failed" cleanupAndExit 1 @@ -1553,6 +1720,9 @@ function uninstallKamailio { removeInitCmd "dsiprouter.sh updatekamconfig" removeDependsOnInit "kamailio.service" + # remove cronjobs for kamailio + cronRemove "${DSIP_PROJECT_DIR}/dsiprouter.sh updatedynamicaddrs" + # Remove the hidden installed file, which denotes if it's installed or not rm -f ${DSIP_SYSTEM_CONFIG_DIR}/.kamailioinstalled @@ -3891,10 +4061,32 @@ function processCMD { ;; # internal command, generates CA dir from CA bundle file updatecacertsdir) - # update dnsmasq config + # update cacerts config RUN_COMMANDS+=(updateCACertsDir) shift + while (( $# > 0 )); do + OPT="$1" + case $OPT in + -debug) + export DEBUG=1 + set -x + shift + ;; + *) # fail on unknown option + printerr "Invalid option [$OPT] for command [$ARG]" + usageOptions + cleanupAndExit 1 + shift + ;; + esac + done + ;; + updatedynamicaddrs) + # update resolved DNS addresses + RUN_COMMANDS+=(updateDynamicAddresses) + shift + while (( $# > 0 )); do OPT="$1" case $OPT in diff --git a/dsiprouter/dsip_lib.sh b/dsiprouter/dsip_lib.sh index f6f69542..f99bed4f 100755 --- a/dsiprouter/dsip_lib.sh +++ b/dsiprouter/dsip_lib.sh @@ -170,25 +170,25 @@ function decryptConfigAttrib() { } export -f decryptConfigAttrib -# $1 == attribute name +# $1 == feature name # $2 == kamailio config file -function enableKamailioConfigAttrib() { +function enableKamailioConfigFeature() { local NAME="$1" local CONFIG_FILE="$2" sed -i -r -e "s~#+(!(define|trydef|redefine)[[:space:]]? $NAME)~#\1~g" ${CONFIG_FILE} } -export -f enableKamailioConfigAttrib +export -f enableKamailioConfigFeature -# $1 == attribute name +# $1 == feature name # $2 == kamailio config file -function disableKamailioConfigAttrib() { +function disableKamailioConfigFeature() { local NAME="$1" local CONFIG_FILE="$2" sed -i -r -e "s~#+(!(define|trydef|redefine)[[:space:]]? $NAME)~##\1~g" ${CONFIG_FILE} } -export -f disableKamailioConfigAttrib +export -f disableKamailioConfigFeature # $1 == name of defined url to change # $2 == value to change url to @@ -204,6 +204,24 @@ function setKamailioConfigDburl() { } export -f setKamailioConfigDburl +# $1 == name of define to change +# $2 == +# $3 == kamailio config file +# $4 == -q (quote as string) +function setKamailioConfigDef() { + local NAME="$1" + local VALUE="$2" + local CONFIG_FILE="$3" + + if [[ "$4" == "-q" ]]; then + VALUE='"'"${VALUE}"'"' + fi + + perl -e "\$name='${NAME}'; \$value='${VALUE}';" \ + -i -pe 's%(#+\!)(define|trydef|redefine)([ \t]+${name}[ \t]+).*%\1\2\3${value}%g' ${CONFIG_FILE} +} +export -f setKamailioConfigDef + # $1 == name of substdef to change # $2 == value to change substdef to # $3 == kamailio config file @@ -388,6 +406,8 @@ export -f ipv6Test # notes: prints internal ip, or empty string if not available # notes: tries ipv4 first then ipv6 function getInternalIP() { + local IPV6_ENABLED=${IPV6_ENABLED:-0} + local IP=$(ip -4 route get $GOOGLE_DNS_IPV4 2>/dev/null | head -1 | grep -oP 'src \K([^\s]+)') if (( ${IPV6_ENABLED} == 1 )) && [[ -z "$IP" ]]; then IP=$(ip -6 route get $GOOGLE_DNS_IPV6 2>/dev/null | head -1 | grep -oP 'src \K([^\s]+)') @@ -470,11 +490,14 @@ export -f getInternalFQDN # notes: will use EXTERNAL_IP if available or look it up dynamically # notes: tries ipv4 first then ipv6 function getExternalFQDN() { + local IPV6_ENABLED=${IPV6_ENABLED:-0} + local EXTERNAL_IP=${EXTERNAL_IP:-$(getExternalIP)} local EXTERNAL_FQDN=$(dig @${GOOGLE_DNS_IPV4} +short -x ${EXTERNAL_IP} 2>/dev/null | head -1 | sed 's/\.$//') if (( ${IPV6_ENABLED} == 1 )) && [[ -z "$EXTERNAL_FQDN" ]]; then EXTERNAL_FQDN=$(dig @${GOOGLE_DNS_IPV6} +short -x ${EXTERNAL_IP} 2>/dev/null | head -1 | sed 's/\.$//') fi + printf '%s' "$EXTERNAL_FQDN" } export -f getExternalFQDN @@ -483,6 +506,7 @@ export -f getExternalFQDN # notes: prints internal CIDR address, or empty string if not available # notes: tries ipv4 first then ipv6 function getInternalCIDR() { + local IPV6_ENABLED=${IPV6_ENABLED:-0} local PREFIX_LEN="" DEF_IFACE="" local IP=$(ip -4 route get $GOOGLE_DNS_IPV4 2>/dev/null | head -1 | grep -oP 'src \K([^\s]+)') @@ -505,6 +529,26 @@ function getInternalCIDR() { } export -f getInternalCIDR +# $1 == host to resolve +# $2 == -a (return all resolved IPs) +# output: IP address(es) of host +function hostToIP() { + local IPV6_ENABLED=${IPV6_ENABLED:-0} + local HOST="$1" + + local IP_ADDR=$(dig @${GOOGLE_DNS_IPV4} +short A ${HOST} 2>/dev/null) + if (( ${IPV6_ENABLED} == 1 )) && [[ -z "$EXTERNAL_FQDN" ]]; then + IP_ADDR=$(dig @${GOOGLE_DNS_IPV6} +short AAAA ${HOST} 2>/dev/null | head -1 | sed 's/\.$//') + fi + + if [[ "$2" == "-a" ]]; then + echo -n "$IP_ADDR" + else + echo -n "$IP_ADDR" | head -1 + fi +} +export -f hostToIP + # $1 == cmd as executed in systemd (by ExecStart=) # notes: take precaution when adding long running functions as they will block startup in boot order # notes: adding init commands on an AMI instance must not be long running processes, otherwise they will fail diff --git a/gui/database/__init__.py b/gui/database/__init__.py index a46612fe..2ba757c7 100644 --- a/gui/database/__init__.py +++ b/gui/database/__init__.py @@ -5,15 +5,16 @@ import os from enum import Enum from datetime import datetime, timedelta -from sqlalchemy import create_engine, MetaData, Table, Column, String -from sqlalchemy.orm import mapper, sessionmaker, scoped_session +from sqlalchemy import create_engine, MetaData, Table, Column, String, func, JSON from sqlalchemy import exc as sql_exceptions +from sqlalchemy.orm import mapper, sessionmaker, scoped_session, attributes +from sqlalchemy.ext.hybrid import hybrid_property, ExprComparator, Comparator +from sqlalchemy.util import memoized_property, update_wrapper import settings -from shared import IO, debugException, dictToStrFields +from shared import IO, debugException, dictToStrFields, strFieldsToDict from util.networking import safeUriToHost, safeFormatSipUri from util.security import AES_CTR - if settings.KAM_DB_TYPE == "mysql": try: import MySQLdb as db_driver @@ -30,7 +31,181 @@ debugException(ex) raise -class Gateways(object): + +# TODO: not fully working yet, see if we can work with upstream devs on this +# this SHOULD allow JSON fields to be accessed / set using d['key']='val' +# class hybrid_dict_property(hybrid_property): +# def __init__( +# self, fget, fset=None, fdel=None, +# fgetitem=None, fsetitem=None, fdelitem=None, +# expr=None, custom_comparator=None, update_expr=None, +# item_expr=None, item_custom_comparator=None, item_update_expr=None, +# ): +# self.fgetitem = fgetitem +# self.fsetitem = fsetitem +# self.fdelitem = fdelitem +# self.item_expr = item_expr +# self.item_custom_comparator = item_custom_comparator +# self.item_update_expr = item_update_expr +# super().__init__( +# fget, fset=fset, fdel=fdel, +# expr=expr, custom_comparator=custom_comparator, update_expr=update_expr, +# ) +# +# def __getitem__(self, instance, key): +# if self.fgetitem is None: +# return self.fget(instance)[key] +# else: +# return self.fgetitem(instance) +# +# def __setitem__(self, instance, key, val): +# if self.fsetitem is None: +# tmp = self.fget(instance) +# tmp[key] = val +# return self.fset(instance, tmp) +# else: +# self.fsetitem(instance, key, val) +# +# def __delitem__(self, instance, key): +# if self.fdelitem is None: +# tmp = self.fget(instance) +# del (tmp[key]) +# self.fset(instance, tmp) +# else: +# self.fdelitem(instance, key) +# +# def get_item(self, fgetitem): +# return self._copy(fgetitem=fgetitem) +# +# def set_item(self, fsetitem): +# return self._copy(fsetitem=fsetitem) +# +# def delete_item(self, fdelitem): +# return self._copy(fdelitem=fdelitem) +# +# def item_expression(self, expr): +# return self._copy(item_expr=expr) +# +# def item_comparator(self, comparator): +# return self._copy(item_custom_comparator=comparator) +# +# def item_update_expression(self, meth): +# return self._copy(item_update_expr=meth) +# +# @memoized_property +# def _item_expr_comparator(self): +# if self.item_custom_comparator is not None: +# return self._get_item_comparator(self.item_custom_comparator) +# elif self.item_expr is not None: +# return self._get_item_expr(self.item_expr) +# else: +# return self._get_item_expr(self.fgetitem) +# +# def _get_item_expr(self, expr): +# def _item_expr(cls): +# return ExprComparator(cls, expr(cls), self) +# +# update_wrapper(_item_expr, expr) +# +# return self._get_item_comparator(_item_expr) +# +# def _get_item_comparator(self, comparator): +# +# proxy_attr = attributes.create_proxied_attribute(self) +# +# def item_expr_comparator(owner): +# return proxy_attr( +# owner, +# self.__name__, +# self, +# comparator(owner), +# doc=comparator.__doc__ or self.__doc__, +# ) +# +# return item_expr_comparator + +class ObjectWithDescription(object): + """ + Handles description field setter/getter for JSON data + """ + + @hybrid_property + def description(self): + return strFieldsToDict(self._description) + + @description.setter + def description(self, val): + self._description = dictToStrFields(val) + + @description.deleter + def description(self): + self._description = {} + + # @description.get_item + # def description(self, key): + # return strFieldsToDict(self._description)[key] + # + # @description.set_item + # def description(self, key, val): + # self._description[key] = val + # + # @description.delete_item + # def description(self, key): + # del(self._description[key]) + + @description.expression + def description(cls): + return func.json_unquote(cls.description) + + @description.update_expression + def description(cls, val): + return [(cls._description, dictToStrFields(val))] + + @description.comparator + def description(cls): + return Comparator(cls._description) + + # @description.item_expression + # def description(cls, key): + # return func.json_unquote(func.json_extract(cls.description, key)) + # + # @description.item_update_expression + # def description(cls, key, val): + # tmp = strFieldsToDict(cls.description) + # tmp[key] = val + # return [(cls.description, dictToStrFields(tmp))] + # + # @description.item_comparator + # def description(cls, key): + # return Comparator(cls.description[key]) + +class ObjectWithTag(object): + """ + Handles tag field setter/getter for JSON data + """ + @hybrid_property + def tag(self): + return strFieldsToDict(self._tag) + + @tag.setter + def tag(self, value): + self._tag = dictToStrFields(value) + + @tag.deleter + def tag(self): + self._tag = {} + + @tag.expression + def tag(cls): + return func.json_unquote(cls.tag) + + @tag.update_expression + def description(cls, value): + return [(cls.tag, dictToStrFields(value))] + + + +class Gateways(ObjectWithDescription): """ Schema for dr_gateways table\n Documentation: `dr_gateways table `_\n @@ -38,35 +213,35 @@ class Gateways(object): The address field can be a full SIP URI, partial URI, or only host; where host portion is an IP or FQDN """ - def __init__(self, name, address, strip, prefix, type, gwgroup=None, addr_id=None, attrs=''): - description = {"name": name} + def __init__(self, name, address, strip, prefix, type, gwgroup=None, addr_list=None, attrs=''): + desc_fields = {'name': name} if gwgroup is not None: - description["gwgroup"] = str(gwgroup) - if addr_id is not None: - description['addr_id'] = str(addr_id) + desc_fields['gwgroup'] = gwgroup + if addr_list is not None: + desc_fields['addr_list'] = addr_list self.type = type self.address = address self.strip = strip self.pri_prefix = prefix self.attrs = attrs - self.description = dictToStrFields(description) + self.description = desc_fields pass -class GatewayGroups(object): +class GatewayGroups(ObjectWithDescription): """ Schema for dr_gw_lists table\n Documentation: `dr_gw_lists table `_ """ def __init__(self, name, gwlist=[], type=settings.FLT_CARRIER): - self.description = "name:{},type:{}".format(name, type) + self.description = {'name': name, 'type': type} self.gwlist = ",".join(str(gw) for gw in gwlist) pass -class Address(object): +class Address(ObjectWithTag): """ Schema for address table\n Documentation: `address table `_\n @@ -75,19 +250,19 @@ class Address(object): """ def __init__(self, name, ip_addr, mask, type, gwgroup=None, port=0): - tag = {"name": name} + tag_fields = {"name": name} if gwgroup is not None: - tag["gwgroup"] = str(gwgroup) + tag_fields["gwgroup"] = gwgroup self.grp = type self.ip_addr = ip_addr self.mask = mask self.port = port - self.tag = dictToStrFields(tag) + self.tag = tag_fields pass -class InboundMapping(object): +class InboundMapping(ObjectWithDescription): """ Partial Schema for modified version of dr_rules table\n Documentation: `dr_rules table `_ @@ -95,7 +270,7 @@ class InboundMapping(object): gwname = Column(String) - def __init__(self, groupid, prefix, gwlist, description=''): + def __init__(self, groupid, prefix, gwlist, description={}): self.groupid = groupid self.prefix = prefix self.gwlist = gwlist @@ -105,13 +280,13 @@ def __init__(self, groupid, prefix, gwlist, description=''): pass -class OutboundRoutes(object): +class OutboundRoutes(ObjectWithDescription): """ Schema for dr_rules table\n Documentation: `dr_rules table `_ """ - def __init__(self, groupid, prefix, timerec, priority, routeid, gwlist, description): + def __init__(self, groupid, prefix, timerec, priority, routeid, gwlist, description={}): self.groupid = groupid self.prefix = prefix self.timerec = timerec @@ -122,12 +297,12 @@ def __init__(self, groupid, prefix, timerec, priority, routeid, gwlist, descript pass -class CustomRouting(object): +class CustomRouting(ObjectWithDescription): """ Schema for dr_custom_rules table\n """ - def __init__(self, locality, ppm, description): + def __init__(self, locality, ppm, description={}): self.locality = locality self.ppm = ppm self.description = description @@ -232,8 +407,8 @@ class dSIPLeases(object): def __init__(self, gwid, sid, ttl): self.gwid = gwid self.sid = sid - t = datetime.now() + timedelta(seconds=ttl) - self.expiration = t.strftime('%Y-%m-%d %H:%M:%S') + now = datetime.now() + timedelta(seconds=ttl) + self.expiration = now.strftime('%Y-%m-%d %H:%M:%S') pass @@ -328,7 +503,6 @@ class dSIPCertificates(object): """ def __init__(self, domain, type, email, cert, key): - self.domain = domain self.type = type self.email = email @@ -337,18 +511,16 @@ def __init__(self, domain, type, email, cert, key): pass -class dSIPDNIDEnrichment(object): +class dSIPDNIDEnrichment(ObjectWithDescription): """ Schema for dsip_dnid_enrich_lnp table\n """ def __init__(self, dnid, country_code='', routing_number='', rule_name=''): - description = {'name': rule_name} - self.dnid = dnid self.country_code = country_code self.routing_number = routing_number - self.description = dictToStrFields(description) + self.description = {'name': rule_name} pass @@ -424,13 +596,13 @@ def __init__(self, did, name="pbx_ip", type=2, value=None, last_modified=datetim pass -class Dispatcher(object): +class Dispatcher(ObjectWithDescription): """ Schema for dispatcher table\n Documentation: `dispatcher table `_ """ - def __init__(self, setid, destination, flags=None, priority=None, attrs=None, description=''): + def __init__(self, setid, destination, flags=None, priority=None, attrs=None, description={}): self.setid = setid self.destination = safeFormatSipUri(destination) self.flags = flags @@ -571,20 +743,20 @@ def createSessionMaker(): # dr_gw_lists_alias.c.drlist_id == dr_groups.c.id, # dr_gw_lists_alias.c.drlist_description == dr_groups.c.description) - mapper(Gateways, dr_gateways) - mapper(Address, address) - mapper(InboundMapping, inboundmapping) - mapper(OutboundRoutes, outboundroutes) + mapper(Gateways, dr_gateways, properties={'_description': dr_gateways.c.description}) + mapper(Address, address, properties={'_description': address.c.tag}) + mapper(InboundMapping, inboundmapping, properties={'_description': inboundmapping.c.description}) + mapper(OutboundRoutes, outboundroutes, properties={'_description': outboundroutes.c.description}) mapper(dSIPDomainMapping, dsip_domain_mapping) mapper(dSIPMultiDomainMapping, dsip_multidomain_mapping) mapper(Subscribers, subscriber) - # mapper(CustomRouting, customrouting) + # mapper(CustomRouting, customrouting, properties={'_description': customrouting.c.description}) mapper(dSIPLCR, dsip_lcr) mapper(UAC, uacreg) - mapper(GatewayGroups, dr_gw_lists) + mapper(GatewayGroups, dr_gw_lists, properties={'_description': dr_gw_lists.c.description}) mapper(Domain, domain) mapper(DomainAttrs, domain_attrs) - mapper(Dispatcher, dispatcher) + mapper(Dispatcher, dispatcher, properties={'_description': dispatcher.c.description}) mapper(dSIPLeases, dsip_endpoint_lease) mapper(dSIPMaintModes, dsip_maintmode) mapper(dSIPCallLimits, dsip_calllimit) @@ -593,7 +765,7 @@ def createSessionMaker(): mapper(dSIPFailFwd, dsip_failfwd) mapper(dSIPCDRInfo, dsip_cdrinfo) mapper(dSIPCertificates, dsip_certificates) - mapper(dSIPDNIDEnrichment, dsip_dnid_enrichment) + mapper(dSIPDNIDEnrichment, dsip_dnid_enrichment, properties={'_description': dsip_dnid_enrichment.c.description}) # mapper(GatewayGroups, gw_join, properties={ # 'id': [dr_groups.c.id, dr_gw_lists_alias.c.drlist_id], diff --git a/gui/dsiprouter.py b/gui/dsiprouter.py index 0c9ad90a..5ecddefe 100755 --- a/gui/dsiprouter.py +++ b/gui/dsiprouter.py @@ -23,9 +23,9 @@ from werkzeug.middleware.proxy_fix import ProxyFix from sysloginit import initSyslogLogger from shared import updateConfig, getCustomRoutes, debugException, debugEndpoint, \ - stripDictVals, strFieldsToDict, dictToStrFields, allowed_file, showError, IO, objToDict, StatusCodes + stripDictVals, allowed_file, showError, IO, objToDict, StatusCodes from util.networking import getInternalIP, getExternalIP, safeUriToHost, safeFormatSipUri, safeStripPort, getInternalCIDR, \ - ipToHost, hostToIP, getFQDN, getHostname + ipToHost, hostToIP, isValidIP, getFQDN, getHostname from database import db_engine, SessionLoader, DummySession, Gateways, Address, InboundMapping, OutboundRoutes, Subscribers, \ dSIPLCR, UAC, GatewayGroups, Domain, DomainAttrs, dSIPDomainMapping, dSIPMultiDomainMapping, Dispatcher, dSIPMaintModes, \ dSIPCallLimits, dSIPHardFwd, dSIPFailFwd @@ -315,6 +315,13 @@ def addUpdateCarrierGroups(): auth_domain = safeUriToHost(auth_domain) if auth_domain is None: raise http_exceptions.BadRequest("Auth domain hostname/address is malformed") + auth_host = safeStripPort(auth_domain) + if not isValidIP(auth_host): + auth_host_addr_list = hostToIP(auth_host, only_first=False) + if auth_host_addr_list is None: + raise http_exceptions.BadRequest("Auth domain hostname/address is malformed") + else: + auth_host_addr_list = [auth_host] if len(auth_proxy) == 0: auth_proxy = auth_domain auth_proxy = safeFormatSipUri(auth_proxy, default_user=r_username) @@ -334,49 +341,57 @@ def addUpdateCarrierGroups(): # Add auth_domain(aka registration server) to the gateway list if authtype == "userpwd": + addr_name = name + "-uac" Uacreg = UAC(gwgroup, r_username, auth_password, realm=auth_realm, auth_username=auth_username, auth_proxy=auth_proxy, local_domain=settings.EXTERNAL_IP_ADDR, remote_domain=auth_domain) - Addr = Address(name + "-uac", auth_domain, 32, settings.FLT_CARRIER, gwgroup=gwgroup) db.add(Uacreg) - db.add(Addr) + for auth_host in auth_host_addr_list: + Addr = Address(addr_name, auth_host, 32, settings.FLT_CARRIER, gwgroup=gwgroup) + db.add(Addr) # Updating else: # config form if len(new_name) > 0: Gwgroup = db.query(GatewayGroups).filter(GatewayGroups.id == gwgroup).first() - gwgroup_fields = strFieldsToDict(Gwgroup.description) + gwgroup_fields = Gwgroup.description old_name = gwgroup_fields['name'] gwgroup_fields['name'] = new_name - Gwgroup.description = dictToStrFields(gwgroup_fields) + Gwgroup.description = gwgroup_fields - Addr = db.query(Address).filter(Address.tag.contains("name:{}-uac".format(old_name))).first() - if Addr is not None: - addr_fields = strFieldsToDict(Addr.tag) - addr_fields['name'] = 'name:{}-uac'.format(new_name) - Addr.tag = dictToStrFields(addr_fields) + addr_name = new_name + "-uac" + addr_old_name = old_name + "-uac" + for Addr in db.query(Address).filter(func.json_extract(Address.tag, '$.name') == addr_old_name).all(): + addr_fields = Addr.tag + addr_fields['name'] = addr_name + Addr.tag = addr_fields # auth form else: + addr_name = name + "-uac" + if authtype == "userpwd": # update uacreg if exists, otherwise create if not db.query(UAC).filter(UAC.l_uuid == gwgroup).update( {'l_username': r_username, 'r_username': r_username, 'auth_username': auth_username, 'auth_password': auth_password, 'r_domain': auth_domain, 'realm': auth_realm, - 'auth_proxy': auth_proxy, 'flags': UAC.FLAGS.REG_ENABLED.value}, synchronize_session=False): + 'auth_proxy': auth_proxy, 'flags': UAC.FLAGS.REG_ENABLED.value}, synchronize_session=False + ): Uacreg = UAC(gwgroup, r_username, auth_password, realm=auth_realm, auth_username=auth_username, auth_proxy=auth_proxy, local_domain=settings.EXTERNAL_IP_ADDR, remote_domain=auth_domain) db.add(Uacreg) - # update address if exists, otherwise create - if not db.query(Address).filter(Address.tag.contains("name:{}-uac".format(name))).update( - {'ip_addr': auth_domain}, synchronize_session=False): - Addr = Address(name + "-uac", auth_domain, 32, settings.FLT_CARRIER, gwgroup=gwgroup) + # delete old addresses + db.query(Address).filter(func.json_extract(Address.tag, '$.name') == addr_name).delete(synchronize_session=False) + + # create new addresses + for auth_host in auth_host_addr_list: + Addr = Address(addr_name, auth_host, 32, settings.FLT_CARRIER, gwgroup=gwgroup) db.add(Addr) else: # delete uacreg and address if they exist db.query(UAC).filter(UAC.l_uuid == gwgroup).delete(synchronize_session=False) - db.query(Address).filter(Address.tag.contains("name:{}-uac".format(name))).delete(synchronize_session=False) + db.query(Address).filter(func.json_extract(Address.tag, '$.name') == addr_name).delete(synchronize_session=False) db.commit() globals.reload_required = True @@ -424,8 +439,7 @@ def deleteCarrierGroups(): gwgroup = form['gwgroup'] gwlist = form['gwlist'] if 'gwlist' in form else '' - - Addrs = db.query(Address).filter(Address.tag.contains("gwgroup:{}".format(gwgroup))) + Addrs = db.query(Address).filter(func.json_extract(Address.tag, "$.gwgroup") == gwgroup) Gwgroup = db.query(GatewayGroups).filter(GatewayGroups.id == gwgroup) gwgroup_row = Gwgroup.first() if gwgroup_row is not None: @@ -499,7 +513,7 @@ def displayCarriers(gwid=None, gwgroup=None, newgwid=None): gateway_rules = {} for rule in rules: if str(gwid) in filter(None, rule.gwlist.split(',')): - gateway_rules[rule.ruleid] = strFieldsToDict(rule.description)['name'] + gateway_rules[rule.ruleid] = rule.description['name'] carrier_rules.append(json.dumps(gateway_rules, separators=(',', ':'))) # get carriers by carrier group @@ -514,7 +528,7 @@ def displayCarriers(gwid=None, gwgroup=None, newgwid=None): gateway_rules = {} for rule in rules: if gateway_id in filter(None, rule.gwlist.split(',')): - gateway_rules[rule.ruleid] = strFieldsToDict(rule.description)['name'] + gateway_rules[rule.ruleid] = rule.description['name'] carrier_rules.append(json.dumps(gateway_rules, separators=(',', ':'))) # get all carriers @@ -525,7 +539,7 @@ def displayCarriers(gwid=None, gwgroup=None, newgwid=None): gateway_rules = {} for rule in rules: if str(gateway.gwid) in filter(None, rule.gwlist.split(',')): - gateway_rules[rule.ruleid] = strFieldsToDict(rule.description)['name'] + gateway_rules[rule.ruleid] = rule.description['name'] carrier_rules.append(json.dumps(gateway_rules, separators=(',', ':'))) return render_template('carriers.html', rows=carriers, routes=carrier_rules, gwgroup=gwgroup, new_gwid=newgwid, @@ -579,22 +593,34 @@ def addUpdateCarriers(): strip = form['strip'] if len(form['strip']) > 0 else '0' prefix = form['prefix'] if len(form['prefix']) > 0 else '' + # validate required args if len(hostname) == 0: raise http_exceptions.BadRequest("Carrier hostname/address is required") - + # properly format the SIP uri sip_addr = safeUriToHost(hostname, default_port=5060) if sip_addr is None: raise http_exceptions.BadRequest("Endpoint hostname/address is malformed") - host_addr = safeStripPort(sip_addr) + # resolve all IP's for this hostname + host = safeStripPort(sip_addr) + if not isValidIP(host): + host_addr_list = hostToIP(host, only_first=False) + if host_addr_list is None: + raise http_exceptions.BadRequest("Endpoint hostname/address is malformed") + else: + host_addr_list = [host] + addr_id_list = [] # Adding if len(gwid) <= 0: if len(gwgroup) > 0: - Addr = Address(name, host_addr, 32, settings.FLT_CARRIER, gwgroup=gwgroup) - db.add(Addr) - db.flush() + for host_addr in host_addr_list: + Addr = Address(name, host_addr, 32, settings.FLT_CARRIER, gwgroup=gwgroup) + db.add(Addr) + db.flush() + addr_id_list.append(Addr.id) - Gateway = Gateways(name, sip_addr, strip, prefix, settings.FLT_CARRIER, gwgroup=gwgroup, addr_id=Addr.id) + Gateway = Gateways(name, sip_addr, strip, prefix, settings.FLT_CARRIER, gwgroup=gwgroup, + addr_list=addr_id_list) db.add(Gateway) db.flush() @@ -606,11 +632,13 @@ def addUpdateCarriers(): Gatewaygroup.gwlist = ','.join(gwlist) else: - Addr = Address(name, host_addr, 32, settings.FLT_CARRIER) - db.add(Addr) - db.flush() + for host_addr in host_addr_list: + Addr = Address(name, host_addr, 32, settings.FLT_CARRIER) + db.add(Addr) + db.flush() + addr_id_list.append(Addr.id) - Gateway = Gateways(name, sip_addr, strip, prefix, settings.FLT_CARRIER, addr_id=Addr.id) + Gateway = Gateways(name, sip_addr, strip, prefix, settings.FLT_CARRIER, addr_list=addr_id_list) db.add(Gateway) # Updating @@ -620,41 +648,30 @@ def addUpdateCarriers(): Gateway.strip = strip Gateway.pri_prefix = prefix - gw_fields = strFieldsToDict(Gateway.description) + gw_fields = Gateway.description gw_fields['name'] = name if len(gwgroup) <= 0: gw_fields['gwgroup'] = gwgroup - # if address exists update - address_exists = False - if 'addr_id' in gw_fields and len(gw_fields['addr_id']) > 0: - Addr = db.query(Address).filter(Address.id == gw_fields['addr_id']).first() - - # if entry is non existent handle in next block - if Addr is not None: - address_exists = True - - Addr.ip_addr = host_addr - addr_fields = strFieldsToDict(Addr.tag) - addr_fields['name'] = name - - if len(gwgroup) > 0: - addr_fields['gwgroup'] = gwgroup - Addr.tag = dictToStrFields(addr_fields) - - # otherwise create the address - if not address_exists: - if len(gwgroup) > 0: - Addr = Address(name, host_addr, 32, settings.FLT_CARRIER, gwgroup=gwgroup) - else: - Addr = Address(name, host_addr, 32, settings.FLT_CARRIER) + # delete old addresses + if 'addr_list' in gw_fields and len(gw_fields['addr_list']) > 0: + db.query(Address).filter(Address.id.in_(gw_fields['addr_list'])).delete( + synchronize_session=False) + # create new addresses + if len(gwgroup) > 0: + gwgroup_field = gwgroup + else: + gwgroup_field = None + for host_addr in host_addr_list: + Addr = Address(name, host_addr, 32, settings.FLT_CARRIER, gwgroup=gwgroup_field) db.add(Addr) db.flush() - gw_fields['addr_id'] = str(Addr.id) + addr_id_list.append(Addr.id) - # gw_fields may be updated above so set after - Gateway.description = dictToStrFields(gw_fields) + # update description fields + gw_fields['addr_list'] = host_addr_list + Gateway.description = gw_fields db.commit() globals.reload_required = True @@ -706,16 +723,15 @@ def deleteCarriers(): Gateway = db.query(Gateways).filter(Gateways.gwid == gwid) Gateway_Row = Gateway.first() - gw_fields = strFieldsToDict(Gateway_Row.description) + gw_fields = Gateway_Row.description # find associated gwgroup if not provided if len(gwgroup) <= 0: gwgroup = gw_fields['gwgroup'] if 'gwgroup' in gw_fields else '' # remove associated address if exists - if 'addr_id' in gw_fields: - Addr = db.query(Address).filter(Address.id == gw_fields['addr_id']) - Addr.delete(synchronize_session=False) + if 'addr_list' in gw_fields: + db.query(Address).filter(Address.id.in_(gw_fields['addr_list'])).delete(synchronize_session=False) # grab any related carrier groups Gatewaygroups = db.execute('SELECT * FROM dr_gw_lists WHERE FIND_IN_SET({}, dr_gw_lists.gwlist)'.format(gwid)) @@ -928,14 +944,14 @@ def deletePBX(): gwid = form['gwid'] name = form['name'] + uac_addr_name = "uac-{}".format(name) gateway = db.query(Gateways).filter(Gateways.gwid == gwid) + db.query(Address).filter(Address.id.in_(gateway.first().description['addr_list'])).delete(synchronize_session=False) + db.query(Address).filter(func.json_extract(Address.tag, "$.name") == uac_addr_name).delete(synchronize_session=False) gateway.delete(synchronize_session=False) - address = db.query(Address).filter(Address.tag.contains("name:{}".format(name))) - address.delete(synchronize_session=False) subscriber = db.query(Subscribers).filter(Subscribers.rpid == gwid) subscriber.delete(synchronize_session=False) - address.delete(synchronize_session=False) domainmultimapping = db.query(dSIPMultiDomainMapping).filter(dSIPMultiDomainMapping.pbx_id == gwid) res = domainmultimapping.options(load_only("domain_list", "attr_list")).first() @@ -1018,9 +1034,9 @@ def displayInboundMapping(): (GatewayGroups.description.like(endpoint_filter)) | (GatewayGroups.description.like(carrier_filter))).all() # sort endpoint groups by name - epgroups.sort(key=lambda x: strFieldsToDict(x.description)['name'].lower()) + epgroups.sort(key=lambda x: x.description['name'].lower()) # sort gateway groups by type then by name - gwgroups.sort(key=lambda x: (strFieldsToDict(x.description)['type'], strFieldsToDict(x.description)['name'].lower())) + gwgroups.sort(key=lambda x: (x.description['type'], x.description['name'].lower())) dids = [] if len(settings.FLOWROUTE_ACCESS_KEY) > 0 and len(settings.FLOWROUTE_SECRET_KEY) > 0: @@ -1104,24 +1120,19 @@ def addUpdateInboundMapping(): raise http_exceptions.BadRequest("Duplicate DID's are not allowed") if "lb_" in gwgroupid: - x = gwgroupid.split("_"); + x = gwgroupid.split("_") gwgroupid = x[1] dispatcher_id = x[2].zfill(4) # Create a gateway - Gateway = Gateways("drouting_to_dispatcher", "localhost",0, dispatcher_id, settings.FLT_PBX, gwgroup=gwgroupid) + Gateway = Gateways("drouting_to_dispatcher", "localhost", 0, dispatcher_id, settings.FLT_PBX, gwgroup=gwgroupid) db.add(Gateway) db.flush() - Addr = Address("myself", settings.INTERNAL_IP_ADDR, 32,1, gwgroup=gwgroupid) - db.add(Addr) - db.flush() - # Define an Inbound Mapping that maps to the newly created gateway gwlist = Gateway.gwid IMap = InboundMapping(settings.FLT_INBOUND, prefix, gwlist, description) db.add(IMap) - db.flush() db.commit() return displayInboundMapping() @@ -1193,28 +1204,23 @@ def addUpdateInboundMapping(): inserts = [] if "lb_" in gwgroupid: - x = gwgroupid.split("_"); + x = gwgroupid.split("_") gwgroupid = x[1] dispatcher_id = x[2].zfill(4) # Create a gateway Gateway = db.query(Gateways).filter(Gateways.description.like(gwgroupid) & Gateways.description.like("lb:{}".format(dispatcher_id))).first() if Gateway: - fields = strFieldsToDict(Gateway.description) + fields = Gateway.description fields['lb'] = dispatcher_id fields['gwgroup'] = gwgroupid - Gateway.update({'prefix':dispatcher_id,'description': dictToStrFields(fields)}) + Gateway.update({'prefix':dispatcher_id,'description': fields}) else: - Gateway = Gateways("drouting_to_dispatcher", "localhost",0, dispatcher_id, settings.FLT_PBX, gwgroup=gwgroupid) + Gateway = Gateways("drouting_to_dispatcher", "localhost", 0, dispatcher_id, settings.FLT_PBX, + gwgroup=gwgroupid) db.add(Gateway) db.flush() - Addr = db.query(Address).filter(Address.ip_addr == settings.INTERNAL_IP_ADDR).first() - if Addr is None: - Addr = Address("myself", settings.INTERNAL_IP_ADDR, 32, 1, gwgroup=gwgroupid) - db.add(Addr) - db.flush() - # Assign Gateway id to the gateway list gwlist = Gateway.gwid @@ -1697,7 +1703,7 @@ def displayOutboundRoutes(): cgroups = db.query(GatewayGroups).filter(GatewayGroups.description.like(carrier_filter)).all() # sort carrier groups by name - cgroups.sort(key=lambda x: strFieldsToDict(x.description)['name'].lower()) + cgroups.sort(key=lambda x: x.description['name'].lower()) teleblock = {} teleblock["gw_enabled"] = settings.TELEBLOCK_GW_ENABLED diff --git a/gui/modules/api/api_routes.py b/gui/modules/api/api_routes.py index 66d52b7c..4df818d2 100644 --- a/gui/modules/api/api_routes.py +++ b/gui/modules/api/api_routes.py @@ -1,22 +1,21 @@ # make sure the generated source files are imported instead of the template ones import sys + sys.path.insert(0, '/etc/dsiprouter/gui') -import os, time, json, random, subprocess, requests, csv, base64, codecs, re, OpenSSL -import urllib.parse as parse +import os, time, json, random, subprocess, requests, csv, base64, codecs, re, dns.resolver from contextlib import closing from collections import OrderedDict from datetime import datetime from flask import Blueprint, jsonify, render_template, request, session, send_file, Response -from sqlalchemy import exc as sql_exceptions, and_,or_ +from sqlalchemy import exc as sql_exceptions, and_, or_ from werkzeug import exceptions as http_exceptions from werkzeug.utils import secure_filename from database import SessionLoader, DummySession, Address, dSIPNotification, Domain, DomainAttrs, dSIPDomainMapping, \ dSIPMultiDomainMapping, Dispatcher, Gateways, GatewayGroups, Subscribers, dSIPLeases, dSIPMaintModes, \ dSIPCallLimits, InboundMapping, dSIPCDRInfo, dSIPCertificates, Dispatcher, dSIPDNIDEnrichment -from shared import allowed_file, dictToStrFields, isCertValid, rowToDict, showApiError, \ - debugEndpoint, StatusCodes, strFieldsToDict, IO, getRequestData -from util.networking import getExternalIP, hostToIP, safeUriToHost, safeStripPort +from shared import allowed_file, isCertValid, rowToDict, showApiError, debugEndpoint, StatusCodes, getRequestData +from util.networking import getExternalIP, hostToIP, safeUriToHost, safeStripPort, isValidIP from util.notifications import sendEmail from util.security import AES_CTR, urandomChars, EasyCrypto, api_security from util.file_handling import isValidFile, change_owner @@ -39,7 +38,6 @@ # we need to abstract out common code between gui and api and standardize routes! - @api.route("/api/v1/kamailio/stats", methods=['GET']) @api_security def getKamailioStats(): @@ -65,6 +63,7 @@ def getKamailioStats(): except Exception as ex: return showApiError(ex) + @api.route("/api/v1/kamailio/health", methods=['GET']) def getSystemHealth(): # defaults.. keep data returned separate from returned metadata @@ -79,7 +78,7 @@ def getSystemHealth(): jsonrpc_payload = {"jsonrpc": "2.0", "method": "tm.stats", "id": 1} r = requests.get('http://127.0.0.1:5060/api/kamailio', json=jsonrpc_payload) if r: - #health_data.['version'] = "5.3.4." + # health_data.['version'] = "5.3.4." http_status = r.status_code if http_status >= 400: response_payload['msg'] = 'Server is down' @@ -94,7 +93,6 @@ def getSystemHealth(): return jsonify(response_payload), http_status - @api.route("/api/v1/kamailio/reload", methods=['GET']) @api_security def reloadKamailio(): @@ -129,7 +127,8 @@ def reloadKamailio(): {'method': 'htable.reload', 'jsonrpc': '2.0', 'id': 1, 'params': ["inbound_failfwd"]}, {'method': 'htable.reload', 'jsonrpc': '2.0', 'id': 1, 'params': ["inbound_prefixmap"]}, {'method': 'uac.reg_reload', 'jsonrpc': '2.0', 'id': 1}, - {'method': 'cfg.sets', 'jsonrpc': '2.0', 'id': 1, 'params': ['teleblock', 'gw_enabled', str(settings.TELEBLOCK_GW_ENABLED)]}, + {'method': 'cfg.sets', 'jsonrpc': '2.0', 'id': 1, + 'params': ['teleblock', 'gw_enabled', str(settings.TELEBLOCK_GW_ENABLED)]}, {'method': 'cfg.sets', 'jsonrpc': '2.0', 'id': 1, 'params': ['server', 'role', settings.ROLE]}, {'method': 'cfg.sets', 'jsonrpc': '2.0', 'id': 1, 'params': ['server', 'api_server', dsip_api_url]}, {'method': 'cfg.sets', 'jsonrpc': '2.0', 'id': 1, 'params': ['server', 'api_token', dsip_api_token]} @@ -201,7 +200,7 @@ def getEndpointLease(): # Convert TTL to Seconds r = re.compile('\d*m|M') if r.match(ttl): - ttl = 60 * int(ttl[0:(len(ttl)-1)]) + ttl = 60 * int(ttl[0:(len(ttl) - 1)]) # Generate some values rand_num = random.randint(1, 200) @@ -384,8 +383,7 @@ def handleInboundMapping(): if res is not None: data = rowToDict(res) data = {'ruleid': data['ruleid'], 'did': data['prefix'], - 'name': strFieldsToDict(data['description'])['name'] if 'name' in strFieldsToDict( - data['description']) else '', + 'name': data['description']['name'] if 'name' in data['description'] else '', 'servers': data['gwlist'].split(',')} payload['data'].append(data) payload['msg'] = 'Rule Found' @@ -401,8 +399,7 @@ def handleInboundMapping(): if res is not None: data = rowToDict(res) data = {'ruleid': data['ruleid'], 'did': data['prefix'], - 'name': strFieldsToDict(data['description'])['name'] if 'name' in strFieldsToDict( - data['description']) else '', + 'name': data['description']['name'] if 'name' in data['description'] else '', 'servers': data['gwlist'].split(',')} payload['data'].append(data) payload['msg'] = 'DID Found' @@ -416,8 +413,7 @@ def handleInboundMapping(): for row in res: data = rowToDict(row) data = {'ruleid': data['ruleid'], 'did': data['prefix'], - 'name': strFieldsToDict(data['description'])['name'] if 'name' in strFieldsToDict( - data['description']) else '', + 'name': data['description']['name'] if 'name' in data['description'] else '', 'servers': data['gwlist'].split(',')} payload['data'].append(data) payload['msg'] = 'Rules Found' @@ -645,9 +641,9 @@ def handleNotificationRequest(): # customize message based on type gwid = data.pop('gwid', None) gw_row = db.query(Gateways).filter(Gateways.gwid == gwid).first() if gwid is not None else None - gw_name = strFieldsToDict(gw_row.description)['name'] if gw_row is not None else '' + gw_name = gw_row.description['name'] if gw_row is not None else '' gwgroup_row = db.query(GatewayGroups).filter(GatewayGroups.id == gwgroupid).first() - gwgroup_name = strFieldsToDict(gwgroup_row.description)['name'] if gwgroup_row is not None else '' + gwgroup_name = gwgroup_row.description['name'] if gwgroup_row is not None else '' if notif_type == dSIPNotification.FLAGS.TYPE_OVERLIMIT.value: data['html_body'] = ( '' @@ -717,9 +713,9 @@ def deleteEndpointGroup(gwgroupid): if endpoints is not None: address_ids = [] for endpoint in endpoints: - description_dict = strFieldsToDict(endpoint.description) - if 'addr_id' in description_dict: - address_ids.append(description_dict['addr_id']) + description_dict = endpoint.description + if 'addr_list' in description_dict: + address_ids.extend(description_dict['addr_list']) db.query(Address).filter(Address.id.in_(address_ids)).delete(synchronize_session=False) endpoints.delete(synchronize_session=False) @@ -736,18 +732,19 @@ def deleteEndpointGroup(gwgroupid): domainmapping = db.query(dSIPMultiDomainMapping).filter(dSIPMultiDomainMapping.pbx_id == gwgroupid) if domainmapping.count() > 0: - # Get list of all domains managed by the endpoint group + # Get list of all domains managed by the endpoint group query = "select distinct did from domain_attrs where name = 'created_by' and value='{}'".format(gwgroupid); domain_attrs = db.execute(query) - did_list=[] - did_list_string="" + did_list = [] + did_list_string = "" for did in domain_attrs: did_list_string = did_list_string + "," + "'" + did[0] + "'" if did_list_string[0][0] == ",": did_list_string = did_list_string[1:] # Delete all domains - query = "delete from domain where did in (select did from domain_attrs where name = 'created_by' and value='{}')".format(gwgroupid); + query = "delete from domain where did in (select did from domain_attrs where name = 'created_by' and value='{}')".format( + gwgroupid); db.execute(query) # Delete all domains_attrs @@ -757,7 +754,8 @@ def deleteEndpointGroup(gwgroupid): # Delete domain mapping, which will stop the fusionpbx sync domainmapping.delete(synchronize_session=False) - dispatcher = db.query(Dispatcher).filter(or_(Dispatcher.setid == gwgroupid, Dispatcher.setid == int(gwgroupid) + 1000)) + dispatcher = db.query(Dispatcher).filter( + or_(Dispatcher.setid == gwgroupid, Dispatcher.setid == int(gwgroupid) + 1000)) if dispatcher is not None: dispatcher.delete(synchronize_session=False) @@ -792,7 +790,7 @@ def getEndpointGroup(gwgroupid): endpointgroup = db.query(GatewayGroups).filter(GatewayGroups.id == gwgroupid).first() if endpointgroup is not None: - gwgroup_data['name'] = strFieldsToDict(endpointgroup.description)['name'] + gwgroup_data['name'] = endpointgroup.description['name'] else: raise http_exceptions.NotFound("Endpoint Group Does Not Exist") @@ -833,7 +831,7 @@ def getEndpointGroup(gwgroupid): ep = {} ep['gwid'] = endpoint.gwid ep['hostname'] = endpoint.address - ep['description'] = strFieldsToDict(endpoint.description)['name'] + ep['description'] = endpoint.description['name'] if dispatcher: ep['weight'] = weightList[endpoint.address] if endpoint.address in weightList else '' else: @@ -905,7 +903,7 @@ def listEndpointGroups(): for endpointgroup in endpointgroups: # Grap the description field, which is comma seperated key/value pair - fields = strFieldsToDict(endpointgroup.description) + fields = endpointgroup.description # append summary of endpoint group data response_payload['data'].append({ @@ -1055,9 +1053,9 @@ def updateEndpointGroups(gwgroupid=None): if Gwgroup is None: raise http_exceptions.NotFound('gwgroup does not exist') gwgroup_data['gwgroupid'] = gwgroupid - gwgroup_desc_dict = strFieldsToDict(Gwgroup.description) + gwgroup_desc_dict = Gwgroup.description gwgroup_desc_dict['name'] = request_payload['name'] if 'name' in request_payload else '' - Gwgroup.description = dictToStrFields(gwgroup_desc_dict) + Gwgroup.description = gwgroup_desc_dict db.flush() # Update concurrent call limit @@ -1138,7 +1136,7 @@ def updateEndpointGroups(gwgroupid=None): # If endpoint sent over is not in the existing endpoint list then remove it gwgroup_filter = "%gwgroup:{}%".format(gwgroupid_str) current_endpoints_lut = { - x.gwid: {'address': x.address, 'description_dict': strFieldsToDict(x.description)} \ + x.gwid: {'address': x.address, 'description_dict': x.description} \ for x in db.query(Gateways).filter(Gateways.description.like(gwgroup_filter)).all() } updated_endpoints = request_payload['endpoints'] if "endpoints" in request_payload else [] @@ -1165,30 +1163,38 @@ def updateEndpointGroups(gwgroupid=None): if authtype == "ip": # for ip auth we must create address records for the endpoint host_addr = safeStripPort(sip_addr) - host_ip = hostToIP(host_addr) - - Addr = Address(name, host_ip, 32, settings.FLT_PBX, gwgroup=gwgroupid) - db.add(Addr) - db.flush() + if not isValidIP(host_addr): + host_addr_list = hostToIP(host_addr, only_first=False) + if host_addr_list is None: + raise http_exceptions.BadRequest("Endpoint hostname/address is malformed") + else: + host_addr_list = [host_addr] + host_addr_id_list = [] + + for host_addr in host_addr_list: + Addr = Address(name, host_addr, 32, settings.FLT_PBX, gwgroup=gwgroupid) + db.add(Addr) + db.flush() + host_addr_id_list.append(Addr.id) Gateway = Gateways(name, sip_addr, strip, prefix, settings.FLT_PBX, gwgroup=gwgroupid, - addr_id=Addr.id) + addr_list=host_addr_id_list) else: # we know this a new endpoint so we don't have to check for any address records here Gateway = Gateways(name, sip_addr, strip, prefix, settings.FLT_PBX, gwgroup=gwgroupid) - # Create dispatcher group with the set id being the gateway group id - dispatcher = Dispatcher(setid=gwgroupid, destination=sip_addr, attrs="weight={}".format(weight),description=name) + dispatcher = Dispatcher(setid=gwgroupid, destination=sip_addr, attrs="weight={}".format(weight), + description=name) db.add(dispatcher) # Create dispatcher for FusionPBX external interface if FusionPBX feature is enabled if int(fusionpbxenabled) > 0: - sip_addr_external = safeUriToHost(hostname, default_port=5080) + sip_addr_external = safeUriToHost(hostname, default_port=5080) # Add 1000 to the gwgroupid so that the setid for the FusionPBX external interface is 1000 apart - dispatcher = Dispatcher(setid=gwgroupid+1000, destination=sip_addr_external, attrs="weight={}".format(weight),description=name) + dispatcher = Dispatcher(setid=gwgroupid + 1000, destination=sip_addr_external, + attrs="weight={}".format(weight), description=name) db.add(dispatcher) - db.add(Gateway) db.flush() gwlist.append(Gateway.gwid) @@ -1226,25 +1232,37 @@ def updateEndpointGroups(gwgroupid=None): if authtype == "ip": # for ip auth we must create address records for the endpoint host_addr = safeStripPort(sip_addr) - host_ip = hostToIP(host_addr) + if not isValidIP(host_addr): + host_addr_list = hostToIP(host_addr, only_first=False) + if host_addr_list is None: + raise http_exceptions.BadRequest("Endpoint hostname/address is malformed") + else: + host_addr_list = [host_addr] + host_addr_id_list = [] + + for host_addr in host_addr_list: + Addr = Address(name, host_addr, 32, settings.FLT_PBX, gwgroup=gwgroupid) + db.add(Addr) + db.flush() + host_addr_id_list.append(Addr.id) + Gateway = Gateways(name, sip_addr, strip, prefix, settings.FLT_PBX, gwgroup=gwgroupid, + addr_list=host_addr_id_list) - Addr = Address(name, host_ip, 32, settings.FLT_PBX, gwgroup=gwgroupid) - db.add(Addr) - db.flush() - Gateway = Gateways(name, sip_addr, strip, prefix, settings.FLT_PBX, gwgroup=gwgroupid, addr_id=Addr.id) else: # we know this a new endpoint so we don't have to check for any address records here Gateway = Gateways(name, sip_addr, strip, prefix, settings.FLT_PBX, gwgroup=gwgroupid) # Create dispatcher group with the set id being the gateway group id - dispatcher = Dispatcher(setid=gwgroupid, destination=sip_addr, attrs="weight={}".format(weight),description=name) + dispatcher = Dispatcher(setid=gwgroupid, destination=sip_addr, attrs="weight={}".format(weight), + description=name) db.add(dispatcher) # Create dispatcher for FusionPBX external interface if FusionPBX feature is enabled if int(fusionpbxenabled) > 0: - sip_addr_external = safeUriToHost(safeStripPort(hostname), default_port=5080) + sip_addr_external = safeUriToHost(safeStripPort(hostname), default_port=5080) # Add 1000 to the gwgroupid so that the setid for the FusionPBX external interface is 1000 apart - dispatcher = Dispatcher(setid=gwgroupid+1000, destination=sip_addr_external, attrs="weight={}".format(weight),description=name) + dispatcher = Dispatcher(setid=gwgroupid + 1000, destination=sip_addr_external, + attrs="weight={}".format(weight), description=name) db.add(dispatcher) @@ -1274,102 +1292,106 @@ def updateEndpointGroups(gwgroupid=None): if authtype == "ip": # for ip auth we must create address records for the endpoint host_addr = safeStripPort(sip_addr) - host_ip = hostToIP(host_addr) - - # if address exists update, otherwise create it - address_exists = False - if 'addr_id' in endpoint_fields and len(endpoint_fields['addr_id']) > 0: - Addr = db.query(Address).filter(Address.id == endpoint_fields['addr_id']).first() - - if Addr is not None: - address_exists = True - - Addr.ip_addr = host_ip - addr_fields = strFieldsToDict(Addr.tag) - addr_fields['name'] = name - addr_fields['gwgroup'] = gwgroupid_str - Addr.tag = dictToStrFields(addr_fields) + if not isValidIP(host_addr): + host_addr_list = hostToIP(host_addr, only_first=False) + if host_addr_list is None: + raise http_exceptions.BadRequest("Endpoint hostname/address is malformed") + else: + host_addr_list = [host_addr] + host_addr_id_list = [] - if not address_exists: - Addr = Address(name, host_ip, 32, settings.FLT_PBX, gwgroup=gwgroupid) + # delete old addresses + if 'addr_list' in endpoint_fields and len(endpoint_fields['addr_list']) > 0: + db.query(Address).filter(Address.id.in_(endpoint_fields['addr_list'])).delete( + synchronize_session=False) + # create new addresses + for host_addr in host_addr_list: + Addr = Address(name, host_addr, 32, settings.FLT_PBX, gwgroup=gwgroupid) db.add(Addr) db.flush() - endpoint_fields['addr_id'] = str(Addr.id) + host_addr_id_list.append(Addr.id) + + # update address list if endpoint has one + if 'addr_list' in endpoint_fields: + endpoint_fields['addr_list'] = host_addr_id_list + else: # if not using ip auth make sure we delete any old address records for the endpoint - if 'addr_id' in endpoint_fields and len(endpoint_fields['addr_id']) > 0: - Addr = db.query(Address).filter(Address.id == endpoint_fields['addr_id']) - if Addr is not None: - Addr.delete(synchronize_session=False) + if 'addr_list' in endpoint_fields and len(endpoint_fields['addr_list']) > 0: + db.query(Address).filter(Address.id.in_(endpoint_fields['addr_list'])).delete( + synchronize_session=False) # remove addr_id field from endpoint description - endpoint_fields.pop("addr_id", None) + endpoint_fields.pop("addr_list", None) # update the endpoint db.query(Gateways).filter(Gateways.gwid == gwid).update( - {"description": dictToStrFields(endpoint_fields), "address": sip_addr, "strip": strip, + {"description": endpoint_fields, "address": sip_addr, "strip": strip, "pri_prefix": prefix}, synchronize_session=False) # update the weight DispatcherEntry = db.query(Dispatcher).filter( (Dispatcher.setid == gwgroupid) & (Dispatcher.destination == "sip:{}".format(sip_addr))).first() - #if weight is None or len(weight) == 0: + # if weight is None or len(weight) == 0: # if DispatcherEntry is not None: # db.delete(DispatcherEntry) - #elif weight: + # elif weight: if DispatcherEntry is not None: db.query(Dispatcher).filter( (Dispatcher.setid == gwgroupid) & (Dispatcher.destination == "sip:{}".format(sip_addr))).update( {"attrs": "weight={}".format(weight)}, synchronize_session=False) else: dispatcher = Dispatcher(setid=gwgroupid, destination=sip_addr, attrs="weight={}".format(weight), - description=name) + description={'name': name}) db.add(dispatcher) if int(fusionpbxenabled) > 0: # update the weight for the external load balancer dispatcher set - sip_addr_external = safeUriToHost(safeStripPort(hostname), default_port=5080) - DispatcherEntry = db.query(Dispatcher).filter((Dispatcher.setid == int(gwgroupid) + 1000) & (Dispatcher.destination == "sip:{}".format(sip_addr_external))).first() + sip_addr_external = safeUriToHost(safeStripPort(hostname), default_port=5080) + DispatcherEntry = db.query(Dispatcher).filter((Dispatcher.setid == int(gwgroupid) + 1000) & ( + Dispatcher.destination == "sip:{}".format(sip_addr_external))).first() if weight is None or len(weight) == 0: if DispatcherEntry is not None: db.delete(DispatcherEntry) elif weight: if DispatcherEntry is not None: - db.query(Dispatcher).filter((Dispatcher.setid == int(gwgroupid) + 1000) & (Dispatcher.destination == "sip:{}".format(sip_addr_external))).update({"attrs":"weight={}".format(weight)},synchronize_session=False) + db.query(Dispatcher).filter((Dispatcher.setid == int(gwgroupid) + 1000) & ( + Dispatcher.destination == "sip:{}".format(sip_addr_external))).update( + {"attrs": "weight={}".format(weight)}, synchronize_session=False) else: - #sip_addr_external = safeUriToHost(hostname, default_port=5080) - #dispatcher = Dispatcher(setid=gwgroupid + 1000, destination=sip_addr_external, attrs="weight={}".format(weight),description=name) - #db.add(dispatcher) + # sip_addr_external = safeUriToHost(hostname, default_port=5080) + # dispatcher = Dispatcher(setid=gwgroupid + 1000, destination=sip_addr_external, attrs="weight={}".format(weight),description=name) + # db.add(dispatcher) pass gwlist.append(gwid) # conditional endpoints to delete # we also cleanup house here in case of stray entries - del_gateways = db.query(Gateways).filter(and_( \ - Gateways.gwid.in_(del_gwids), \ - Gateways.address != "localhost" \ - )) - del_gateways_cleanup = db.query(Gateways).filter(and_( \ - Gateways.description.like(gwgroup_filter), \ - Gateways.gwid.notin_(gwlist), \ - Gateways.address != "localhost" \ - )) + del_gateways = db.query(Gateways).filter(and_( + Gateways.gwid.in_(del_gwids), + Gateways.address != "localhost" + )) + del_gateways_cleanup = db.query(Gateways).filter(and_( + Gateways.description.like(gwgroup_filter), + Gateways.gwid.notin_(gwlist), + Gateways.address != "localhost" + )) # make sure we delete any associated address entries del_addr_ids = [] for gateway in del_gateways.union(del_gateways_cleanup): - description_dict = strFieldsToDict(gateway.description) - if 'addr_id' in description_dict: - del_addr_ids.append(description_dict['addr_id']) + description_dict = gateway.description + if 'addr_list' in description_dict: + del_addr_ids.extend(description_dict['addr_list']) db.query(Address).filter(Address.id.in_(del_addr_ids)).delete(synchronize_session=False) - # delete the dispatcher entries that correspond to the endpoints/gateways that was Deleted - del_addrs = [] + # delete the dispatcher entries that correspond to the endpoints/gateways that was Deleted + del_addr_ids = [] for gateway in del_gateways.union(del_gateways_cleanup): - del_addrs.append("sip:{}".format(gateway.address)) - db.query(Dispatcher).filter(and_(Dispatcher.setid == gwgroupid, Dispatcher.destination.in_(del_addrs))).delete(synchronize_session=False) - - + del_addr_ids.append("sip:{}".format(gateway.address)) + db.query(Dispatcher).filter( + Dispatcher.setid == gwgroupid & Dispatcher.destination.in_(del_addr_ids) + ).delete(synchronize_session=False) del_gateways.delete(synchronize_session=False) del_gateways_cleanup.delete(synchronize_session=False) @@ -1446,7 +1468,7 @@ def updateEndpointGroups(gwgroupid=None): if not deleteTaggedCronjob(gwgroupid): raise Exception('Crontab entry could not be deleted') - # Update FusionPBX + # Update FusionPBX # Convert fusionpbxenabled variable to int if isinstance(fusionpbxenabled, str): @@ -1555,7 +1577,7 @@ def addEndpointGroups(data=None, endpointGroupType=None, domain=None): """ db = DummySession() - fusionpbxenabled=0 + fusionpbxenabled = 0 # use a whitelist to avoid possible buffer overflow vulns or crashes VALID_REQUEST_DATA_ARGS = { @@ -1709,31 +1731,40 @@ def addEndpointGroups(data=None, endpointGroupType=None, domain=None): raise http_exceptions.BadRequest("Endpoint hostname/address is malformed") if authtype == "ip": + # for ip auth we must create address records for the endpoint host_addr = safeStripPort(sip_addr) - host_ip = hostToIP(host_addr) + if not isValidIP(host_addr): + host_addr_list = hostToIP(host_addr, only_first=False) + if host_addr_list is None: + raise http_exceptions.BadRequest("Endpoint hostname/address is malformed") + else: + host_addr_list = [host_addr] + host_addr_id_list = [] - Addr = Address(name, host_ip, 32, settings.FLT_PBX, gwgroup=gwgroupid) - db.add(Addr) - db.flush() - Gateway = Gateways(name, sip_addr, strip, prefix, settings.FLT_PBX, gwgroup=gwgroupid, addr_id=Addr.id, - attrs=attrs) + for host_addr in host_addr_list: + Addr = Address(name, host_addr, 32, settings.FLT_PBX, gwgroup=gwgroupid) + db.add(Addr) + db.flush() + host_addr_id_list.append(Addr.id) + Gateway = Gateways(name, sip_addr, strip, prefix, settings.FLT_PBX, gwgroup=gwgroupid, + addr_list=host_addr_id_list, attrs=attrs) else: Gateway = Gateways(name, sip_addr, strip, prefix, settings.FLT_PBX, gwgroup=gwgroupid, attrs=attrs) - # Create dispatcher group with the set id being the gateway group id - dispatcher = Dispatcher(setid=gwgroupid, destination=sip_addr, attrs="weight={}".format(weight),description=name) + dispatcher = Dispatcher(setid=gwgroupid, destination=sip_addr, attrs="weight={}".format(weight), + description=name) db.add(dispatcher) # Create dispatcher for FusionPBX external interface if FusionPBX feature is enabled if fusionpbxenabled: - sip_addr_external = safeUriToHost(hostname, default_port=5080) + sip_addr_external = safeUriToHost(hostname, default_port=5080) # Add 1000 to the gwgroupid so that the setid for the FusionPBX external interface is 1000 apart - dispatcher = Dispatcher(setid=gwgroupid+1000, destination=sip_addr_external, attrs="weight={}".format(weight),description=name) + dispatcher = Dispatcher(setid=gwgroupid + 1000, destination=sip_addr_external, + attrs="weight={}".format(weight), description=name) db.add(dispatcher) - db.add(Gateway) db.flush() gwlist.append(Gateway.gwid) @@ -1745,14 +1776,14 @@ def addEndpointGroups(data=None, endpointGroupType=None, domain=None): # Update Gateway group with the Dispatcher ID. It's denoted with the LB field gwgroup = db.query(GatewayGroups).filter(GatewayGroups.id == gwgroupid).first() if gwgroup is not None: - fields = strFieldsToDict(gwgroup.description) + fields = gwgroup.description fields['lb'] = gwgroupid if fusionpbxenabled: fields['lb_ext'] = gwgroupid + 1000 # Update the GatewayGroup with the lists of gateways db.query(GatewayGroups).filter(GatewayGroups.id == gwgroupid).update( - {'gwlist': gwlist_str, 'description': dictToStrFields(fields)}, synchronize_session=False) + {'gwlist': gwlist_str, 'description': fields}, synchronize_session=False) # Setup notifications if 'notifications' in request_payload: @@ -1855,7 +1886,7 @@ def getNumberEnrichment(rule_id=None): 'dnid': rule.dnid, 'country_code': rule.country_code, 'routing_number': rule.routing_number, - 'rule_name': strFieldsToDict(rule.description)['name'] + 'rule_name': rule.description['name'] }) else: raise http_exceptions.NotFound("Enrichment Rule Does Not Exist") @@ -1869,7 +1900,7 @@ def getNumberEnrichment(rule_id=None): 'dnid': rule.dnid, 'country_code': rule.country_code, 'routing_number': rule.routing_number, - 'rule_name': strFieldsToDict(rule.description)['name'] + 'rule_name': rule.description['name'] }) response_payload['msg'] = 'Enrichment Rule(s) found' @@ -2105,7 +2136,7 @@ def updateNumberEnrichment(rule_id=None, request_payload=None): else: rule_id = rule_data.pop('rule_id') description = {'name': rule_data.pop('rule_name')} - rule_data['description'] = dictToStrFields(description) + rule_data['description'] = description if not db.query(dSIPDNIDEnrichment).filter(dSIPDNIDEnrichment.id == rule_id).update( rule_data, synchronize_session=False): @@ -2420,7 +2451,7 @@ def fetchNumberEnrichment(request_payload=None): 'dnid': rule.dnid, 'country_code': rule.country_code, 'routing_number': rule.routing_number, - 'rule_name': strFieldsToDict(rule.description)['name'] + 'rule_name': rule.description['name'] }) globals.reload_required = True @@ -2467,7 +2498,7 @@ def generateCDRS(gwgroupid, type=None, email=False, dtfilter=datetime.min, cdrfi gwgroup = db.query(GatewayGroups).filter(GatewayGroups.id == gwgroupid).first() if gwgroup is not None: - gwgroupName = strFieldsToDict(gwgroup.description)['name'] + gwgroupName = gwgroup.description['name'] else: response_payload['status'] = "0" response_payload['message'] = "Endpont group doesn't exist" @@ -2498,7 +2529,7 @@ def generateCDRS(gwgroupid, type=None, email=False, dtfilter=datetime.min, cdrfi ORDER BY t1.call_start_time DESC;""" ).format(gwgroupid=gwgroupid, dtfilter=dtfilter) - rows = db.execute(query) + rows = db.execute(query) cdrs = [] for row in rows: data = {} @@ -2798,18 +2829,17 @@ def getOptionMessageStatus(domain): if not response: return False - try: # Loop thru each record in the dispatcher list - for record in range(0,len(records)): + for record in range(0, len(records)): sets = records[record] # Loop thru each set for set in sets: - #print("{},{}".format(sets[set]['ID'],domain)) + # print("{},{}".format(sets[set]['ID'],domain)) # Loop thru each target targets = sets[set]['TARGETS'] # Loop thru each destination within a target - for dest in range(0,len(targets)): + for dest in range(0, len(targets)): # Grab the destination body and flags # The Body contains the domain name of the destionation dest_body = format(targets[dest]['DEST']['ATTRS']['BODY']) @@ -2845,8 +2875,8 @@ def testConnectivity(domain): test_data['hostname_check'] = True # Try again, but use Google DNS resolver if the check fails with local DNS else: - # Does the IP address of this server resolve to the domain - import dns.resolver + # TODO: dnsmasq should handle forwarding to external resolvers + # this code shouldn't be needed # Get the IP address of the domain from Google DNS resolver = dns.resolver.Resolver() diff --git a/gui/modules/dnid_enrichment/dnid_enrichment.sql b/gui/modules/dnid_enrichment/dnid_enrichment.sql index 731ae17b..bf0b939f 100644 --- a/gui/modules/dnid_enrichment/dnid_enrichment.sql +++ b/gui/modules/dnid_enrichment/dnid_enrichment.sql @@ -6,7 +6,7 @@ CREATE TABLE dsip_dnid_enrich_lnp ( dnid varchar(64) NOT NULL, country_code varchar(64) NOT NULL DEFAULT '', routing_number varchar(64) NOT NULL DEFAULT '', - description varchar(128) NOT NULL DEFAULT '', + description varchar(255) NOT NULL DEFAULT '{}', PRIMARY KEY (id) ) ENGINE = InnoDB DEFAULT CHARSET = utf8; diff --git a/gui/modules/dnid_enrichment/install.sh b/gui/modules/dnid_enrichment/install.sh index 9b082e50..238d3372 100755 --- a/gui/modules/dnid_enrichment/install.sh +++ b/gui/modules/dnid_enrichment/install.sh @@ -34,7 +34,7 @@ function installSQL { function install { installSQL - enableKamailioConfigAttrib 'WITH_DNID_LNP_ENRICHMENT' ${DSIP_KAMAILIO_CONFIG_FILE} + enableKamailioConfigFeature 'WITH_DNID_LNP_ENRICHMENT' ${DSIP_KAMAILIO_CONFIG_FILE} systemctl restart kamailio if systemctl is-active --quiet kamailio; then @@ -47,7 +47,7 @@ function install { } function uninstall { - disableKamailioConfigAttrib 'WITH_DNID_LNP_ENRICHMENT' ${DSIP_KAMAILIO_CONFIG_FILE} + disableKamailioConfigFeature 'WITH_DNID_LNP_ENRICHMENT' ${DSIP_KAMAILIO_CONFIG_FILE} systemctl restart kamailio if systemctl is-active --quiet kamailio; then diff --git a/gui/modules/domain/domain_routes.py b/gui/modules/domain/domain_routes.py index 19e4ccc4..7ff59dab 100644 --- a/gui/modules/domain/domain_routes.py +++ b/gui/modules/domain/domain_routes.py @@ -1,5 +1,4 @@ -from flask import Blueprint, session, render_template -from flask import Flask, render_template, request, redirect, abort, flash, session, url_for, send_from_directory +from flask import Blueprint, session from sqlalchemy import case, func, exc as sql_exceptions from werkzeug import exceptions as http_exceptions from database import SessionLoader, DummySession, Domain, DomainAttrs, dSIPDomainMapping, dSIPMultiDomainMapping, Dispatcher, Gateways, Address @@ -7,7 +6,6 @@ from shared import * import settings import globals -import re domains = Blueprint('domains', __name__) diff --git a/gui/settings.py b/gui/settings.py index 682ecc67..53467eca 100644 --- a/gui/settings.py +++ b/gui/settings.py @@ -83,13 +83,14 @@ SQLALCHEMY_SQL_DEBUG = False # These constants shouldn't be modified -# FLT_CARRIER/FLT_PBX: type in dr_gateways table -# FLT_MSTEAMS: type in dr_gateways table +# FLT_CARRIER/FLT_PBX: type in dr_gateways/address table +# FLT_MSTEAMS/FLT_INTERNAL: type in dr_gateways/address table # FLT_OUTBOUND/FLT_INBOUND: groupid in dr_rules table # FLT_LCR_MIN/FLT_FWD_MIN: range of groupid in dr_rules table FLT_CARRIER = 8 FLT_PBX = 9 FLT_MSTEAMS = 22 +FLT_INTERNAL = 20 FLT_OUTBOUND = 8000 FLT_INBOUND = 9000 FLT_LCR_MIN = 10000 diff --git a/gui/shared.py b/gui/shared.py index c93e285f..dd2632c5 100644 --- a/gui/shared.py +++ b/gui/shared.py @@ -77,15 +77,10 @@ def rowToDict(row): return d def strFieldsToDict(fields_str): - fields = {} - for field in fields_str.split(','): - if ':' in field: - tmp = field.split(':', 1) - fields[tmp[0]] = tmp[1] - return fields + return json.loads(fields_str) def dictToStrFields(fields_dict): - return ','.join("{}:{}".format(k, v) for k, v in fields_dict.items()) + return json.dumps(fields_dict) def updateConfig(config_obj, field_dict, hot_reload=False): """ diff --git a/gui/util/networking.py b/gui/util/networking.py index 8b946966..64238c3d 100644 --- a/gui/util/networking.py +++ b/gui/util/networking.py @@ -120,7 +120,7 @@ def getip(url): return next((x for x in results if x is not None), None) -def hostToIP(host, ip_ver=''): +def hostToIP(host, ip_ver='', only_first=True): """ Convert host to IP Address\n Supports conversion to IPv4 and IPv6\n @@ -130,18 +130,26 @@ def hostToIP(host, ip_ver=''): :type host: str :param ip_ver: IP version to use :type ip_ver: str - :return: IP address of host - :rtype: str|None + :param only_first: Whether to return all resolved addresses + :type only_first: bool + :return: IP address(es) of host + :rtype: str|set|None """ if ip_ver == '4' or len(ip_ver) == 0: try: - return socket.getaddrinfo(host, 0, socket.AF_INET)[0][4][0] + if only_first: + return socket.getaddrinfo(host, 0, socket.AF_INET)[0][4][0] + else: + return set([x[4][0] for x in socket.getaddrinfo(host, 0, socket.AF_INET)]) except: pass if ip_ver == '6' or len(ip_ver) == 0: try: - return socket.getaddrinfo(host, 0, socket.AF_INET6)[0][4][0] + if only_first: + return socket.getaddrinfo(host, 0, socket.AF_INET6)[0][4][0] + else: + return set([x[4][0] for x in socket.getaddrinfo(host, 0, socket.AF_INET6)]) except: pass return None diff --git a/kamailio/defaults/address.csv b/kamailio/defaults/address.csv index 59546829..65c5f2c9 100644 --- a/kamailio/defaults/address.csv +++ b/kamailio/defaults/address.csv @@ -1,74 +1,75 @@ -null;FLT_CARRIER;54.172.60.0;32;0;name:Twilio NA-Virginia Signalling,gwgroup:1 -null;FLT_CARRIER;54.172.60.1;32;0;name:Twilio NA-Virginia Signalling,gwgroup:1 -null;FLT_CARRIER;54.172.60.2;32;0;name:Twilio NA-Virginia Signalling,gwgroup:1 -null;FLT_CARRIER;54.172.60.3;32;0;name:Twilio NA-Virginia Signalling,gwgroup:1 -null;FLT_CARRIER;54.244.51.0;32;0;name:Twilio NA-Oregon Signalling,gwgroup:1 -null;FLT_CARRIER;54.244.51.1;32;0;name:Twilio NA-Oregon Signalling,gwgroup:1 -null;FLT_CARRIER;54.244.51.2;32;0;name:Twilio NA-Oregon Signalling,gwgroup:1 -null;FLT_CARRIER;54.244.51.3;32;0;name:Twilio NA-Oregon Signalling,gwgroup:1 -null;FLT_CARRIER;54.172.60.0;23;0;name:Twilio NA-Virginia Media,gwgroup:1 -null;FLT_CARRIER;34.203.250.0;23;0;name:Twilio NA-Virginia Media,gwgroup:1 -null;FLT_CARRIER;54.244.51.0;24;0;name:Twilio NA-Oregon Media,gwgroup:1 -null;FLT_CARRIER;52.41.52.34;32;0;name:Skyetel North West Inbound,gwgroup:2 -null;FLT_CARRIER;52.8.201.128;32;0;name:Skyetel South West Inbound,gwgroup:2 -null;FLT_CARRIER;52.60.138.31;32;0;name:Skyetel North East Inbound,gwgroup:2 -null;FLT_CARRIER;50.17.48.216;32;0;name:Skyetel South East Inbound,gwgroup:2 -null;FLT_CARRIER;35.156.192.164;32;0;name:Skyetel Europe Inbound,gwgroup:2 -null;FLT_CARRIER;term.skyetel.com;32;0;name:Skyetel 1st Priority Outbound Call,gwgroup:2 -null;FLT_CARRIER;52.41.52.34;32;0;name:Skyetel 2nd Priority Outbound Call,gwgroup:2 -null;FLT_CARRIER;52.8.201.128;32;0;name:Skyetel 3rd Priority Outbound Call,gwgroup:2 -null;FLT_CARRIER;50.17.48.216;32;0;name:Skyetel 4rd Priority Outbound Call,gwgroup:2 -null;FLT_CARRIER;52.32.223.28;32;0;name:Skyetel North West High Cost Outbound Traffic,gwgroup:2 -null;FLT_CARRIER;52.4.178.107;32;0;name:Skyetel South East High Cost Outbound Traffic,gwgroup:2 -null;FLT_CARRIER;147.75.60.160;32;0;name:Flowroute US-West-WA,gwgroup:3 -null;FLT_CARRIER;34.210.91.112;32;0;name:Flowroute US-West-OR,gwgroup:3 -null;FLT_CARRIER;147.75.65.192;32;0;name:Flowroute US-East-NJ,gwgroup:3 -null;FLT_CARRIER;34.226.36.32;32;0;name:Flowroute US-East-VA,gwgroup:3 -null;FLT_CARRIER;81.201.82.45;32;0;name:Voxbone Belgium,gwgroup:4 -null;FLT_CARRIER;81.201.84.195;32;0;name:Voxbone LA,gwgroup:4 -null;FLT_CARRIER;81.201.85.45;32;0;name:Voxbone NYC,gwgroup:4 -null;FLT_CARRIER;81.201.83.45;32;0;name:Voxbone Germany,gwgroup:4 -null;FLT_CARRIER;81.201.86.45;32;0;name:Voxbone Hong Kong,gwgroup:4 -null;FLT_CARRIER;81.201.84.195;32;0;name:Voxbone Australia,gwgroup:4 -null;FLT_CARRIER;64.136.174.30;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;64.136.173.22;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;209.166.128.200;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;192.240.151.100;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;64.136.173.31;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;64.136.174.20;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;209.166.154.70;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;64.136.174.65;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;64.136.173.23;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;209.166.128.201;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;192.240.151.101;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;64.136.173.65;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;64.136.174.65;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;64.136.174.21;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;209.166.154.71;32;0;name:VoIP Innovations Inbound Carrier,gwgroup:5 -null;FLT_CARRIER;64.136.174.30;32;0;name:VoIP Innovations Outbound Conversational Carrier,gwgroup:6 -null;FLT_CARRIER;64.136.173.22;32;0;name:VoIP Innovations Outbound Conversational Carrier,gwgroup:6 -null;FLT_CARRIER;209.166.128.200;32;0;name:VoIP Innovations Outbound Conversational Carrier,gwgroup:6 -null;FLT_CARRIER;192.240.151.100;32;0;name:VoIP Innovations Outbound Conversational Carrier,gwgroup:6 -null;FLT_CARRIER;72.15.219.140;32;0;name:Thinq Carrier,gwgroup:7 -null;FLT_CARRIER;216.147.191.157;32;0;name:Voxtelesys Carrier,gwgroup:8 -null;FLT_CARRIER;64.34.181.47;32;0;name:Les.net Carrier,gwgroup:9 -null;FLT_CARRIER;208.68.17.52;32;0;name:ThinkTel Carrier,gwgroup:10 -null;FLT_CARRIER;206.80.250.100;32;0;name:ThinkTel Carrier,gwgroup:10 -null;FLT_CARRIER;209.197.130.80;32;0;name:ThinkTel Carrier,gwgroup:10 -null;FLT_MSTEAMS;52.114.132.46;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;52.114.14.70;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;52.114.148.0;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;52.114.16.74;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;52.114.20.29;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;52.114.7.24;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;52.114.75.24;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;52.114.76.76;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;52.127.64.33;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;52.127.64.34;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;52.127.88.59;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;52.127.92.64;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;sip.pstnhub.microsoft.com;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;sip2.pstnhub.microsoft.com;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;sip3.pstnhub.microsoft.com;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;sip.pstnhub.dod.teams.microsoft.us;32;0;name:msteams-sbc,gwgroup:0 -null;FLT_MSTEAMS;sip.pstnhub.gov.teams.microsoft.us;32;0;name:msteams-sbc,gwgroup:0 +null;FLT_CARRIER;54.172.60.0;32;0;{"name":"Twilio NA-Virginia Signalling","gwgroup":"1"} +null;FLT_CARRIER;54.172.60.1;32;0;{"name":"Twilio NA-Virginia Signalling","gwgroup":"1"} +null;FLT_CARRIER;54.172.60.2;32;0;{"name":"Twilio NA-Virginia Signalling","gwgroup":"1"} +null;FLT_CARRIER;54.172.60.3;32;0;{"name":"Twilio NA-Virginia Signalling","gwgroup":"1"} +null;FLT_CARRIER;54.244.51.0;32;0;{"name":"Twilio NA-Oregon Signalling","gwgroup":"1"} +null;FLT_CARRIER;54.244.51.1;32;0;{"name":"Twilio NA-Oregon Signalling","gwgroup":"1"} +null;FLT_CARRIER;54.244.51.2;32;0;{"name":"Twilio NA-Oregon Signalling","gwgroup":"1"} +null;FLT_CARRIER;54.244.51.3;32;0;{"name":"Twilio NA-Oregon Signalling","gwgroup":"1"} +null;FLT_CARRIER;54.172.60.0;23;0;{"name":"Twilio NA-Virginia Media","gwgroup":"1"} +null;FLT_CARRIER;34.203.250.0;23;0;{"name":"Twilio NA-Virginia Media","gwgroup":"1"} +null;FLT_CARRIER;54.244.51.0;24;0;{"name":"Twilio NA-Oregon Media","gwgroup":"1"} +null;FLT_CARRIER;52.41.52.34;32;0;{"name":"Skyetel North West Inbound","gwgroup":"2"} +null;FLT_CARRIER;52.8.201.128;32;0;{"name":"Skyetel South West Inbound","gwgroup":"2"} +null;FLT_CARRIER;52.60.138.31;32;0;{"name":"Skyetel North East Inbound","gwgroup":"2"} +null;FLT_CARRIER;50.17.48.216;32;0;{"name":"Skyetel South East Inbound","gwgroup":"2"} +null;FLT_CARRIER;35.156.192.164;32;0;{"name":"Skyetel Europe Inbound","gwgroup":"2"} +null;FLT_CARRIER;term.skyetel.com;32;0;{"name":"Skyetel 1st Priority Outbound Call","gwgroup":"2"} +null;FLT_CARRIER;52.41.52.34;32;0;{"name":"Skyetel 2nd Priority Outbound Call","gwgroup":"2"} +null;FLT_CARRIER;52.8.201.128;32;0;{"name":"Skyetel 3rd Priority Outbound Call","gwgroup":"2"} +null;FLT_CARRIER;50.17.48.216;32;0;{"name":"Skyetel 4rd Priority Outbound Call","gwgroup":"2"} +null;FLT_CARRIER;52.32.223.28;32;0;{"name":"Skyetel North West High Cost Outbound Traffic","gwgroup":"2"} +null;FLT_CARRIER;52.4.178.107;32;0;{"name":"Skyetel South East High Cost Outbound Traffic","gwgroup":"2"} +null;FLT_CARRIER;147.75.60.160;32;0;{"name":"Flowroute US-West-WA","gwgroup":"3"} +null;FLT_CARRIER;34.210.91.112;32;0;{"name":"Flowroute US-West-OR","gwgroup":"3"} +null;FLT_CARRIER;147.75.65.192;32;0;{"name":"Flowroute US-East-NJ","gwgroup":"3"} +null;FLT_CARRIER;34.226.36.32;32;0;{"name":"Flowroute US-East-VA","gwgroup":"3"} +null;FLT_CARRIER;81.201.82.45;32;0;{"name":"Voxbone Belgium","gwgroup":"4"} +null;FLT_CARRIER;81.201.84.195;32;0;{"name":"Voxbone LA","gwgroup":"4"} +null;FLT_CARRIER;81.201.85.45;32;0;{"name":"Voxbone NYC","gwgroup":"4"} +null;FLT_CARRIER;81.201.83.45;32;0;{"name":"Voxbone Germany","gwgroup":"4"} +null;FLT_CARRIER;81.201.86.45;32;0;{"name":"Voxbone Hong Kong","gwgroup":"4"} +null;FLT_CARRIER;81.201.84.195;32;0;{"name":"Voxbone Australia","gwgroup":"4"} +null;FLT_CARRIER;64.136.174.30;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;64.136.173.22;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;209.166.128.200;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;192.240.151.100;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;64.136.173.31;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;64.136.174.20;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;209.166.154.70;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;64.136.174.65;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;64.136.173.23;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;209.166.128.201;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;192.240.151.101;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;64.136.173.65;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;64.136.174.65;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;64.136.174.21;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;209.166.154.71;32;0;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5"} +null;FLT_CARRIER;64.136.174.30;32;0;{"name":"VoIP Innovations Outbound Conversational Carrier","gwgroup":"6"} +null;FLT_CARRIER;64.136.173.22;32;0;{"name":"VoIP Innovations Outbound Conversational Carrier","gwgroup":"6"} +null;FLT_CARRIER;209.166.128.200;32;0;{"name":"VoIP Innovations Outbound Conversational Carrier","gwgroup":"6"} +null;FLT_CARRIER;192.240.151.100;32;0;{"name":"VoIP Innovations Outbound Conversational Carrier","gwgroup":"6"} +null;FLT_CARRIER;72.15.219.140;32;0;{"name":"Thinq Carrier","gwgroup":"7"} +null;FLT_CARRIER;216.147.191.157;32;0;{"name":"Voxtelesys Carrier","gwgroup":"8"} +null;FLT_CARRIER;64.34.181.47;32;0;{"name":"Les.net Carrier","gwgroup":"9"} +null;FLT_CARRIER;208.68.17.52;32;0;{"name":"ThinkTel Carrier","gwgroup":"10"} +null;FLT_CARRIER;206.80.250.100;32;0;{"name":"ThinkTel Carrier","gwgroup":"10"} +null;FLT_CARRIER;209.197.130.80;32;0;{"name":"ThinkTel Carrier","gwgroup":"10"} +null;FLT_MSTEAMS;52.114.132.46;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;52.114.14.70;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;52.114.148.0;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;52.114.16.74;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;52.114.20.29;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;52.114.7.24;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;52.114.75.24;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;52.114.76.76;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;52.127.64.33;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;52.127.64.34;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;52.127.88.59;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;52.127.92.64;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;sip.pstnhub.microsoft.com;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;sip2.pstnhub.microsoft.com;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;sip3.pstnhub.microsoft.com;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;sip.pstnhub.dod.teams.microsoft.us;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_MSTEAMS;sip.pstnhub.gov.teams.microsoft.us;32;0;{"name":"msteams-sbc","gwgroup":"0"} +null;FLT_INTERNAL;INTERNAL_IP;INTERNAL_NET_PREFIX;0;{"name":"dsip-internal","gwgroup":"0"} diff --git a/kamailio/defaults/address.sql b/kamailio/defaults/address.sql index 3244abdd..ac29a03c 100644 --- a/kamailio/defaults/address.sql +++ b/kamailio/defaults/address.sql @@ -1,3 +1,4 @@ -- update address table to fit our storage requirements ALTER TABLE address - MODIFY COLUMN tag varchar(255) NOT NULL DEFAULT ''; + MODIFY COLUMN tag varchar(255) NOT NULL DEFAULT '{}', + ADD CONSTRAINT CHECK (JSON_VALID(tag)); diff --git a/kamailio/defaults/carrierfailureroute.sql b/kamailio/defaults/carrierfailureroute.sql new file mode 100644 index 00000000..e65647b1 --- /dev/null +++ b/kamailio/defaults/carrierfailureroute.sql @@ -0,0 +1,4 @@ +-- update carrierfailureroute table to fit our storage requirements +ALTER TABLE carrierfailureroute + MODIFY COLUMN description varchar(255) NOT NULL DEFAULT '{}', + ADD CONSTRAINT CHECK (JSON_VALID(description)); diff --git a/kamailio/defaults/carrierroute.sql b/kamailio/defaults/carrierroute.sql new file mode 100644 index 00000000..c41b6925 --- /dev/null +++ b/kamailio/defaults/carrierroute.sql @@ -0,0 +1,4 @@ +-- update carrierroute table to fit our storage requirements +ALTER TABLE carrierroute + MODIFY COLUMN description varchar(255) NOT NULL DEFAULT '{}', + ADD CONSTRAINT CHECK (JSON_VALID(description)); diff --git a/kamailio/defaults/dispatcher.sql b/kamailio/defaults/dispatcher.sql index 6319b916..880a6580 100644 --- a/kamailio/defaults/dispatcher.sql +++ b/kamailio/defaults/dispatcher.sql @@ -1,4 +1,4 @@ -- update dispatcher schema to fit our storage requirements ALTER TABLE dispatcher MODIFY COLUMN attrs varchar(255) NOT NULL DEFAULT '', - MODIFY COLUMN description varchar(255) NOT NULL DEFAULT ''; + MODIFY COLUMN description varchar(255) NOT NULL DEFAULT '{}'; diff --git a/kamailio/defaults/domainpolicy.sql b/kamailio/defaults/domainpolicy.sql new file mode 100644 index 00000000..8b839f69 --- /dev/null +++ b/kamailio/defaults/domainpolicy.sql @@ -0,0 +1,4 @@ +-- update domainpolicy table to fit our storage requirements +ALTER TABLE domainpolicy + MODIFY COLUMN description varchar(255) NOT NULL DEFAULT '{}', + ADD CONSTRAINT CHECK (JSON_VALID(description)); diff --git a/kamailio/defaults/dr_gateways.csv b/kamailio/defaults/dr_gateways.csv index 7bfcdbb7..bafd403a 100644 --- a/kamailio/defaults/dr_gateways.csv +++ b/kamailio/defaults/dr_gateways.csv @@ -1,54 +1,54 @@ -null;FLT_CARRIER;54.172.60.0;0;;;name:Twilio NA-Virginia Carrier,gwgroup:1,addr_id:1 -null;FLT_CARRIER;54.172.60.1;0;;;name:Twilio NA-Virginia Carrier,gwgroup:1,addr_id:2 -null;FLT_CARRIER;54.172.60.2;0;;;name:Twilio NA-Virginia Carrier,gwgroup:1,addr_id:3 -null;FLT_CARRIER;54.172.60.3;0;;;name:Twilio NA-Virginia Carrier,gwgroup:1,addr_id:4 -null;FLT_CARRIER;54.244.51.0;0;;;name:Twilio NA-Oregon Carrier,gwgroup:1,addr_id:5 -null;FLT_CARRIER;54.244.51.1;0;;;name:Twilio NA-Oregon Carrier,gwgroup:1,addr_id:6 -null;FLT_CARRIER;54.244.51.2;0;;;name:Twilio NA-Oregon Carrier,gwgroup:1,addr_id:7 -null;FLT_CARRIER;54.244.51.3;0;;;name:Twilio NA-Oregon Carrier,gwgroup:1,addr_id:8 -null;FLT_CARRIER;52.41.52.34;0;;;name:Skyetel North West Inbound,gwgroup:2,addr_id:12 -null;FLT_CARRIER;52.8.201.128;0;;;name:Skyetel South West Inbound,gwgroup:2,addr_id:13 -null;FLT_CARRIER;52.60.138.31;0;;;name:Skyetel North East Inbound,gwgroup:2,addr_id:14 -null;FLT_CARRIER;50.17.48.216;0;;;name:Skyetel South East Inbound,gwgroup:2,addr_id:15 -null;FLT_CARRIER;35.156.192.164;0;;;name:Skyetel Europe Inbound,gwgroup:2,addr_id:16 -null;FLT_CARRIER;term.skyetel.com;0;;;name:Skyetel 1st Priority Outbound Call,gwgroup:2,addr_id:17 -null;FLT_CARRIER;52.41.52.34;0;;;name:Skyetel 2nd Priority Outbound Call,gwgroup:2,addr_id:18 -null;FLT_CARRIER;52.8.201.128;0;;;name:Skyetel 3rd Priority Outbound Call,gwgroup:2,addr_id:19 -null;FLT_CARRIER;50.17.48.216;0;;;name:Skyetel 4rd Priority Outbound Call,gwgroup:2,addr_id:20 -null;FLT_CARRIER;52.32.223.28;0;;;name:Skyetel North West High Cost Outbound Traffic,gwgroup:2,addr_id:21 -null;FLT_CARRIER;52.4.178.107;0;;;name:Skyetel South East High Cost Outbound Traffic,gwgroup:2,addr_id:22 -null;FLT_CARRIER;147.75.60.160;0;;;name:Flowroute US-West-WA,gwgroup:3,addr_id:23 -null;FLT_CARRIER;34.210.91.112;0;;;name:Flowroute US-West-OR,gwgroup:3,addr_id:24 -null;FLT_CARRIER;147.75.65.192;0;;;name:Flowroute US-East-NJ,gwgroup:3,addr_id:25 -null;FLT_CARRIER;34.226.36.32;0;;;name:Flowroute US-East-VA,gwgroup:3,addr_id:26 -null;FLT_CARRIER;81.201.82.45;0;;;name:Voxbone Belgium,gwgroup:4,addr_id:27 -null;FLT_CARRIER;81.201.84.195;0;;;name:Voxbone LA,gwgroup:4,addr_id:28 -null;FLT_CARRIER;81.201.85.45;0;;;name:Voxbone NYC,gwgroup:4,addr_id:29 -null;FLT_CARRIER;81.201.83.45;0;;;name:Voxbone Germany,gwgroup:4,addr_id:30 -null;FLT_CARRIER;81.201.86.45;0;;;name:Voxbone Hong Kong,gwgroup:4,addr_id:31 -null;FLT_CARRIER;81.201.84.195;0;;;name:Voxbone Australia,gwgroup:4,addr_id:32 -null;FLT_CARRIER;64.136.174.30;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:33 -null;FLT_CARRIER;64.136.173.22;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:34 -null;FLT_CARRIER;209.166.128.200;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:35 -null;FLT_CARRIER;192.240.151.100;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:36 -null;FLT_CARRIER;64.136.173.31;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:37 -null;FLT_CARRIER;64.136.174.20;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:38 -null;FLT_CARRIER;209.166.154.70;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:39 -null;FLT_CARRIER;64.136.174.65;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:40 -null;FLT_CARRIER;64.136.173.23;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:41 -null;FLT_CARRIER;209.166.128.201;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:42 -null;FLT_CARRIER;192.240.151.101;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:43 -null;FLT_CARRIER;64.136.173.65;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:44 -null;FLT_CARRIER;64.136.174.65;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:45 -null;FLT_CARRIER;64.136.174.21;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:46 -null;FLT_CARRIER;209.166.154.71;0;;;name:VoIP Innovations Inbound Carrier,gwgroup:5,addr_id:47 -null;FLT_CARRIER;64.136.174.30;0;;;name:VoIP Innovations Outbound Conversational Carrier,gwgroup:6,addr_id:48 -null;FLT_CARRIER;64.136.173.22;0;;;name:VoIP Innovations Outbound Conversational Carrier,gwgroup:6,addr_id:49 -null;FLT_CARRIER;209.166.128.200;0;;;name:VoIP Innovations Outbound Conversational Carrier,gwgroup:6,addr_id:50 +null;FLT_CARRIER;54.172.60.0;0;;;{"name":"Twilio NA-Virginia Carrier","gwgroup":"1","addr_list":[1]} +null;FLT_CARRIER;54.172.60.1;0;;;{"name":"Twilio NA-Virginia Carrier","gwgroup":"1","addr_list":[2]} +null;FLT_CARRIER;54.172.60.2;0;;;{"name":"Twilio NA-Virginia Carrier","gwgroup":"1","addr_list":[3]} +null;FLT_CARRIER;54.172.60.3;0;;;{"name":"Twilio NA-Virginia Carrier","gwgroup":"1","addr_list":[4]} +null;FLT_CARRIER;54.244.51.0;0;;;{"name":"Twilio NA-Oregon Carrier","gwgroup":"1","addr_list":[5]} +null;FLT_CARRIER;54.244.51.1;0;;;{"name":"Twilio NA-Oregon Carrier","gwgroup":"1","addr_list":[6]} +null;FLT_CARRIER;54.244.51.2;0;;;{"name":"Twilio NA-Oregon Carrier","gwgroup":"1","addr_list":[7]} +null;FLT_CARRIER;54.244.51.3;0;;;{"name":"Twilio NA-Oregon Carrier","gwgroup":"1","addr_list":[8]} +null;FLT_CARRIER;52.41.52.34;0;;;{"name":"Skyetel North West Inbound","gwgroup":"2","addr_list":[12]} +null;FLT_CARRIER;52.8.201.128;0;;;{"name":"Skyetel South West Inbound","gwgroup":"2","addr_list":[13]} +null;FLT_CARRIER;52.60.138.31;0;;;{"name":"Skyetel North East Inbound","gwgroup":"2","addr_list":[14]} +null;FLT_CARRIER;50.17.48.216;0;;;{"name":"Skyetel South East Inbound","gwgroup":"2","addr_list":[15]} +null;FLT_CARRIER;35.156.192.164;0;;;{"name":"Skyetel Europe Inbound","gwgroup":"2","addr_list":[16]} +null;FLT_CARRIER;term.skyetel.com;0;;;{"name":"Skyetel 1st Priority Outbound Call","gwgroup":"2","addr_list":[17]} +null;FLT_CARRIER;52.41.52.34;0;;;{"name":"Skyetel 2nd Priority Outbound Call","gwgroup":"2","addr_list":[18]} +null;FLT_CARRIER;52.8.201.128;0;;;{"name":"Skyetel 3rd Priority Outbound Call","gwgroup":"2","addr_list":[19]} +null;FLT_CARRIER;50.17.48.216;0;;;{"name":"Skyetel 4rd Priority Outbound Call","gwgroup":"2","addr_list":[20]} +null;FLT_CARRIER;52.32.223.28;0;;;{"name":"Skyetel North West High Cost Outbound Traffic","gwgroup":"2","addr_list":[21]} +null;FLT_CARRIER;52.4.178.107;0;;;{"name":"Skyetel South East High Cost Outbound Traffic","gwgroup":"2","addr_list":[22]} +null;FLT_CARRIER;147.75.60.160;0;;;{"name":"Flowroute US-West-WA","gwgroup":"3","addr_list":[23]} +null;FLT_CARRIER;34.210.91.112;0;;;{"name":"Flowroute US-West-OR","gwgroup":"3","addr_list":[24]} +null;FLT_CARRIER;147.75.65.192;0;;;{"name":"Flowroute US-East-NJ","gwgroup":"3","addr_list":[25]} +null;FLT_CARRIER;34.226.36.32;0;;;{"name":"Flowroute US-East-VA","gwgroup":"3","addr_list":[26]} +null;FLT_CARRIER;81.201.82.45;0;;;{"name":"Voxbone Belgium","gwgroup":"4","addr_list":[27]} +null;FLT_CARRIER;81.201.84.195;0;;;{"name":"Voxbone LA","gwgroup":"4","addr_list":[28]} +null;FLT_CARRIER;81.201.85.45;0;;;{"name":"Voxbone NYC","gwgroup":"4","addr_list":[29]} +null;FLT_CARRIER;81.201.83.45;0;;;{"name":"Voxbone Germany","gwgroup":"4","addr_list":[30]} +null;FLT_CARRIER;81.201.86.45;0;;;{"name":"Voxbone Hong Kong","gwgroup":"4","addr_list":[31]} +null;FLT_CARRIER;81.201.84.195;0;;;{"name":"Voxbone Australia","gwgroup":"4","addr_list":[32]} +null;FLT_CARRIER;64.136.174.30;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[33]} +null;FLT_CARRIER;64.136.173.22;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[34]} +null;FLT_CARRIER;209.166.128.200;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[35]} +null;FLT_CARRIER;192.240.151.100;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[36]} +null;FLT_CARRIER;64.136.173.31;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[37]} +null;FLT_CARRIER;64.136.174.20;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[38]} +null;FLT_CARRIER;209.166.154.70;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[39]} +null;FLT_CARRIER;64.136.174.65;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[40]} +null;FLT_CARRIER;64.136.173.23;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[41]} +null;FLT_CARRIER;209.166.128.201;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[42]} +null;FLT_CARRIER;192.240.151.101;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[43]} +null;FLT_CARRIER;64.136.173.65;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[44]} +null;FLT_CARRIER;64.136.174.65;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[45]} +null;FLT_CARRIER;64.136.174.21;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[46]} +null;FLT_CARRIER;209.166.154.71;0;;;{"name":"VoIP Innovations Inbound Carrier","gwgroup":"5","addr_list":[47]} +null;FLT_CARRIER;64.136.174.30;0;;;{"name":"VoIP Innovations Outbound Conversational Carrier","gwgroup":"6","addr_list":[48]} +null;FLT_CARRIER;64.136.173.22;0;;;{"name":"VoIP Innovations Outbound Conversational Carrier","gwgroup":"6","addr_list":[49]} +null;FLT_CARRIER;209.166.128.200;0;;;{"name":"VoIP Innovations Outbound Conversational Carrier","gwgroup":"6","addr_list":[50]} null;FLT_CARRIER;192.240.151.100;0;;;name:VoIP Innovations Outbound Conversational Carrier,gwgroup:6,addr_1d:51 -null;FLT_CARRIER;72.15.219.140;0;;;name:Thinq Carrier,gwgroup:7,addr_id:52 -null;FLT_CARRIER;216.147.191.157;0;;;name:Voxtelesys Carrier,gwgroup:8,addr_id:53 -null;FLT_CARRIER;64.34.181.47;0;;;name:Les.net Carrier,gwgroup:9,addr_id:54 -null;FLT_CARRIER;208.68.17.52;0;;;name:ThinkTel Carrier,gwgroup:10,addr_id:55 -null;FLT_CARRIER;206.80.250.100;0;;;name:ThinkTel Carrier,gwgroup:10,addr_id:56 -null;FLT_CARRIER;209.197.130.80;0;;;name:ThinkTel Carrier,gwgroup:10,addr_id:57 +null;FLT_CARRIER;72.15.219.140;0;;;{"name":"Thinq Carrier","gwgroup":"7","addr_list":[52]} +null;FLT_CARRIER;216.147.191.157;0;;;{"name":"Voxtelesys Carrier","gwgroup":"8","addr_list":[53]} +null;FLT_CARRIER;64.34.181.47;0;;;{"name":"Les.net Carrier","gwgroup":"9","addr_list":[54]} +null;FLT_CARRIER;208.68.17.52;0;;;{"name":"ThinkTel Carrier","gwgroup":"10","addr_list":[55]} +null;FLT_CARRIER;206.80.250.100;0;;;{"name":"ThinkTel Carrier","gwgroup":"10","addr_list":[56]} +null;FLT_CARRIER;209.197.130.80;0;;;{"name":"ThinkTel Carrier","gwgroup":"10","addr_list":[57]} diff --git a/kamailio/defaults/dr_gateways.sql b/kamailio/defaults/dr_gateways.sql index d90043d2..e749e1e7 100644 --- a/kamailio/defaults/dr_gateways.sql +++ b/kamailio/defaults/dr_gateways.sql @@ -2,7 +2,8 @@ ALTER TABLE dr_gateways MODIFY COLUMN pri_prefix varchar(64) NOT NULL DEFAULT '', MODIFY COLUMN attrs varchar(255) NOT NULL DEFAULT '', - MODIFY COLUMN description varchar(255) NOT NULL DEFAULT ''; + MODIFY COLUMN description varchar(255) NOT NULL DEFAULT '{}', + ADD CONSTRAINT CHECK (JSON_VALID(description)); -- update dr_gateways attrs column when entry created DROP TRIGGER IF EXISTS insert_dr_gateways; diff --git a/kamailio/defaults/dr_groups.sql b/kamailio/defaults/dr_groups.sql new file mode 100644 index 00000000..6e5b4d14 --- /dev/null +++ b/kamailio/defaults/dr_groups.sql @@ -0,0 +1,4 @@ +-- update dr_groups table to fit our storage requirements +ALTER TABLE dr_groups + MODIFY COLUMN description varchar(255) NOT NULL DEFAULT '{}', + ADD CONSTRAINT CHECK (JSON_VALID(description)); diff --git a/kamailio/defaults/dr_gw_lists.csv b/kamailio/defaults/dr_gw_lists.csv index 191cd64b..06b533d7 100644 --- a/kamailio/defaults/dr_gw_lists.csv +++ b/kamailio/defaults/dr_gw_lists.csv @@ -1,10 +1,10 @@ -null;1,2,3,4,5,6,7,8;name:Twilio NA CarrierGroup,type:8 -null;9,10,11,12,13,14,15,16,17,18,19;name:Skyetel CarrierGroup,type:8 -null;20,21,22,23;name:Flowroute CarrierGroup,type:8 -null;24,25,26,27,28,29;name:Voxbone CarrierGroup,type:8 -null;30,31,32,33,34,35,36,37,38,39,40,41,42,43,44;name:VoIP Innovations Inbound CarrierGroup,type:8 -null;45,46,47,48;name:VoIP Innovations Outbound Conversational CarrierGroup,type:8 -null;49;name:Thinq CarrierGroup,type:8 -null;50;name:Voxtelesys CarrierGroup,type:8 -null;51;name:Les.net CarrierGroup,type:8 -null;52,53,54;name:ThinkTel CarrierGroup,type:8 +null;1,2,3,4,5,6,7,8;{"name":"Twilio NA CarrierGroup","type":8} +null;9,10,11,12,13,14,15,16,17,18,19;{"name":"Skyetel CarrierGroup","type":8} +null;20,21,22,23;{"name":"Flowroute CarrierGroup","type":8} +null;24,25,26,27,28,29;{"name":"Voxbone CarrierGroup","type":8} +null;30,31,32,33,34,35,36,37,38,39,40,41,42,43,44;{"name":"VoIP Innovations Inbound CarrierGroup","type":8} +null;45,46,47,48;{"name":"VoIP Innovations Outbound Conversational CarrierGroup","type":8} +null;49;{"name":"Thinq CarrierGroup","type":8} +null;50;{"name":"Voxtelesys CarrierGroup","type":8} +null;51;{"name":"Les.net CarrierGroup","type":8} +null;52,53,54;{"name":"ThinkTel CarrierGroup","type":8} diff --git a/kamailio/defaults/dr_gw_lists.sql b/kamailio/defaults/dr_gw_lists.sql index 323768c3..a127638a 100644 --- a/kamailio/defaults/dr_gw_lists.sql +++ b/kamailio/defaults/dr_gw_lists.sql @@ -1,3 +1,4 @@ -- update dr_gw_lists schema to fit our storage requirements ALTER TABLE dr_gw_lists - MODIFY COLUMN description varchar(255) NOT NULL DEFAULT ''; + MODIFY COLUMN description varchar(255) NOT NULL DEFAULT '{}', + ADD CONSTRAINT CHECK (JSON_VALID(description)); diff --git a/kamailio/defaults/dr_rules.csv b/kamailio/defaults/dr_rules.csv index 01c45d98..ac4fca7a 100644 --- a/kamailio/defaults/dr_rules.csv +++ b/kamailio/defaults/dr_rules.csv @@ -1 +1 @@ -null;FLT_OUTBOUND;;;;;#2;name:Default Outbound Route +null;FLT_OUTBOUND;;;;;#2;{"name":"Default Outbound Route"} diff --git a/kamailio/defaults/dr_rules.sql b/kamailio/defaults/dr_rules.sql index 9c413066..dc928dfb 100644 --- a/kamailio/defaults/dr_rules.sql +++ b/kamailio/defaults/dr_rules.sql @@ -1,4 +1,5 @@ -- update dr_rules schema to fit our storage requirements ALTER TABLE dr_rules MODIFY COLUMN routeid varchar(255) NOT NULL, - MODIFY COLUMN description varchar(255) NOT NULL DEFAULT ''; + MODIFY COLUMN description varchar(255) NOT NULL DEFAULT '{}', + ADD CONSTRAINT CHECK (JSON_VALID(description)); diff --git a/kamailio/defaults/globalblacklist.sql b/kamailio/defaults/globalblacklist.sql new file mode 100644 index 00000000..ed20c1c9 --- /dev/null +++ b/kamailio/defaults/globalblacklist.sql @@ -0,0 +1,4 @@ +-- update globalblacklist table to fit our storage requirements +ALTER TABLE globalblacklist + MODIFY COLUMN description varchar(255) NOT NULL DEFAULT '{}', + ADD CONSTRAINT CHECK (JSON_VALID(description)); diff --git a/kamailio/defaults/lcr_gw.sql b/kamailio/defaults/lcr_gw.sql new file mode 100644 index 00000000..f3168107 --- /dev/null +++ b/kamailio/defaults/lcr_gw.sql @@ -0,0 +1,4 @@ +-- update lcr_gw table to fit our storage requirements +ALTER TABLE lcr_gw + MODIFY COLUMN tag varchar(255) NOT NULL DEFAULT '{}', + ADD CONSTRAINT CHECK (JSON_VALID(tag)); diff --git a/kamailio/defaults/speed_dial.sql b/kamailio/defaults/speed_dial.sql new file mode 100644 index 00000000..7b6d5c62 --- /dev/null +++ b/kamailio/defaults/speed_dial.sql @@ -0,0 +1,4 @@ +-- update speed_dial table to fit our storage requirements +ALTER TABLE speed_dial + MODIFY COLUMN description varchar(255) NOT NULL DEFAULT '{}', + ADD CONSTRAINT CHECK (JSON_VALID(description)); diff --git a/kamailio/defaults/trusted.sql b/kamailio/defaults/trusted.sql new file mode 100644 index 00000000..d4ea21b4 --- /dev/null +++ b/kamailio/defaults/trusted.sql @@ -0,0 +1,4 @@ +-- update trusted table to fit our storage requirements +ALTER TABLE trusted + MODIFY COLUMN tag varchar(255) NOT NULL DEFAULT '{}', + ADD CONSTRAINT CHECK (JSON_VALID(tag)); diff --git a/kamailio/kamailio_dsiprouter.cfg b/kamailio/kamailio_dsiprouter.cfg index fd728d5f..105450d9 100644 --- a/kamailio/kamailio_dsiprouter.cfg +++ b/kamailio/kamailio_dsiprouter.cfg @@ -109,7 +109,7 @@ import_file "kamailio-local.cfg" #!define FLT_SRC_SIP 17 #!define FLT_SRC_WS 18 #!define FLB_WS_DEVICE 19 - +#!define FLT_INTERNAL 20 #!define FLT_SERVERNAT 21 #!define FLT_MSTEAMS 22 #!define FLB_SRC_MSTEAMS 23 @@ -544,6 +544,7 @@ modparam("auth_db", "use_domain", MULTIDOMAIN) #!ifdef WITH_IPAUTH modparam("permissions", "db_url", DBURL) modparam("permissions", "db_mode", 1) +modparam("permissions", "load_backends", 3) #!endif #!endif