Files
docker-open5gs-prod-999700/smsc/kamailio_smsc.cfg
2025-08-21 01:09:37 +00:00

445 lines
12 KiB
INI

#!KAMAILIO
#
# This config file implements the basic P-CSCF functionality
# - web: http://www.kamailio.org
# - git: http://sip-router.org
#
# Refer to the Core CookBook at http://www.kamailio.org/dokuwiki/doku.php
# for an explanation of possible statements, functions and parameters.
#
# Direct your questions about this file to: <sr-users@lists.kamailio.org>.
#
# For more information about the various parameters, functions and statements
# try http://sip-router.org/wiki/ .
#
include_file "smsc.cfg"
####### Global Parameters #########
debug=2
log_stderror=no
sip_warning=no
children=4
user_agent_header="User-Agent: Kamailio SMSC"
server_header="Server: Kamailio SMSC"
log_name="smsc"
log_prefix_mode=1
log_prefix="{$mt $hdr(CSeq) $ci $cfg(route)} "
/* comment the next line to enable the auto discovery of local aliases
based on reverse DNS on IPs (default on) */
auto_aliases=no
check_via=no # (cmd. line: -v)
dns=no # (cmd. line: -r)
rev_dns=no # (cmd. line: -R)
tcp_accept_no_cl=yes
#!define SMS_3GPP 1
#!define SMS_TEXT 2
alias=SMSC_SERVER
# ------------------ module loading ----------------------------------
mpath="/usr/lib64/kamailio/modules_k/:/usr/lib64/kamailio/modules/:/usr/lib/kamailio/modules_k/:/usr/lib/kamailio/modules/:/usr/lib/x86_64-linux-gnu/kamailio/modules/:/usr/local/lib64/kamailio/modules"
# (we try both the lib64 and the lib directory)
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "corex.so"
loadmodule "smsops.so"
loadmodule "xlog.so"
loadmodule "maxfwd.so"
loadmodule "textops.so"
loadmodule "sl.so"
loadmodule "sanity.so"
loadmodule "siputils.so"
loadmodule "pv.so"
loadmodule "uac.so"
loadmodule "http_client.so"
loadmodule "xhttp.so"
loadmodule "utils.so"
loadmodule "json.so"
loadmodule "enum.so"
loadmodule "db_mysql.so"
loadmodule "dialplan.so"
loadmodule "sqlops.so"
loadmodule "htable.so"
loadmodule "rtimer.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "pua.so"
loadmodule "pua_reginfo.so"
modparam("sqlops", "sqlcon", SMS_DB_URL)
modparam("dialplan", "db_url", DIALPLAN_PUA_DB_URL)
modparam("uac", "restore_mode", "none")
modparam("htable", "htable", "publish_sent=>size=8;autoexpire=SUBSCRIBE_EXPIRE")
modparam("htable", "htable", "sms_retries=>size=8;autoexpire=SUBSCRIBE_EXPIRE")
# time interval set to 3 seconds
modparam("rtimer", "timer", "name=sms;interval=3;mode=1;")
modparam("rtimer", "exec", "timer=sms;route=SMS_WORKER")
modparam("pua_reginfo", "server_address", "sip:SMSC_SERVER")
modparam("pua_reginfo", "publish_reginfo", 0)
modparam("pua", "db_url", DIALPLAN_PUA_DB_URL)
####### Routing Logic ########
# Main SIP request routing logic
# - processing of any incoming SIP request starts with this route
route {
xlog("L_DBG", "$rm ($fu ($si:$sp) to $tu, $ci)\n");
# per request initial checks
route(REQINIT);
if (is_method("NOTIFY")) {
route(NOTIFY);
send_reply("202", "Accepted");
exit;
}
if (!is_method("MESSAGE")) {
append_to_reply("Allow: MESSAGE,NOTIFY\r\n");
send_reply("405", "Method not allowed");
exit;
}
if ($cT == "application/vnd.3gpp.sms") {
route(SMS_FROM_3GPP);
} else if ($cT == "text/plain") {
route(SMS_FROM_SIP);
} else {
send_reply("488", "Content-Type not supported");
exit;
}
}
######################################################################
# Helper routes (Basic-Checks, NAT-Handling/RTP-Control, XML-RPC)
######################################################################
# Per SIP request initial checks
route[REQINIT] {
# Trace this message
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
exit;
}
if(!sanity_check("1511", "7")) {
xlog("Malformed SIP message from $si:$sp\n");
exit;
}
# Reply to OPTIONS:
if (is_method("OPTIONS") && (uri==myself)) {
options_reply();
exit;
}
# Ignore Re-Transmits:
if (t_lookup_request()) {
exit;
}
}
######################################################################
# SMS from VoLTE Handsets
######################################################################
route[SMS_FROM_3GPP] {
#!ifdef WITH_DEBUG
xlog("3GPP-SMS: $rm ($fu ($si:$sp) to $tu, $ci)\n");
xlog("SMS for $tpdu(destination) \"$tpdu(payload)\" (Valid: $tpdu(validity) )\n");
#!endif
send_reply("202", "Accepted");
if (isRPDATA()) {
$uac_req(method) = "MESSAGE";
$uac_req(ruri) = $ai;
$uac_req(furi) = "sip:"+SMSC_SERVER;
$uac_req(turi) = $ai;
$uac_req(hdrs) = "Content-Type: application/vnd.3gpp.sms\r\nRequest-Disposition: no-fork\r\nAccept-Contact: *;+g.3gpp.smsip\r\n";
$uac_req(body) = $smsack;
uac_req_send();
$avp(from) = $(ai{uri.user});
$avp(to) = $tpdu(destination);
$avp(dcs) = $tpdu(coding);
# Translate "To":
dp_translate("1", "$avp(to)/$avp(to)");
$avp(text) = $tpdu(payload);
#!ifdef WITH_DEBUG
xlog("SMS from 3GPP/VoLTE\n");
xlog("-------------------------------------\n");
xlog("FROM $avp(from)\n");
xlog("TO $avp(to)\n");
xlog("TEXT $avp(text)\n");
xlog("DCS $avp(dcs)\n");
#!endif
route(SMS);
}
exit;
}
######################################################################
# SMS from OTT Handsets
######################################################################
route[SMS_FROM_SIP] {
send_reply("200", "OK");
$avp(from) = $(ai{uri.user});
# Translate "To":
$avp(to) = $tU;
dp_translate("1", "$avp(to)/$avp(to)");
$avp(text) = $rb;
#!ifdef WITH_DEBUG
xlog("SMS from SIP/OTT\n");
xlog("-------------------------------------\n");
xlog("FROM $avp(from)\n");
xlog("TO $avp(to)\n");
xlog("TEXT $avp(text)\n");
#!endif
route(SMS);
exit;
}
######################################################################
# SMS from other networks
######################################################################
event_route[xhttp:request] {
if ($(hu{url.querystring}{s.len}) > 0) {
$avp(from) = $(hu{url.querystring}{param.value,msisdn,&});
$avp(to) = $(hu{url.querystring}{param.value,to,&});
$avp(text) = $(hu{url.querystring}{param.value,text,&}{s.replace,+,%20}{s.unescape.user});
$avp(from_outbound) = 1;
#!ifdef WITH_DEBUG
xlog("SMS from Outbound ($hu)\n");
xlog("-------------------------------------\n");
xlog("FROM $avp(from)\n");
xlog("TO $avp(to)\n");
xlog("TEXT $avp(text)\n");
#!endif
if ($avp(to) == "491771782261")
$avp(to) = "494046895124";
if ($avp(to) == "491771782319")
$avp(to) = "494034927220";
route(SMS);
}
xhttp_reply("200", "OK", "text/html", "<html><body>OK - [$si:$sp]</body></html>");
}
######################################################################
# SMS to VoLTE Handsets
######################################################################
route[SMS_TO_3GPP] {
#!ifdef WITH_DEBUG
xlog("SMS to 3GPP/VoLTE\n");
xlog("-------------------------------------\n");
xlog("FROM $avp(from)\n");
xlog("TO $avp(to)\n");
xlog("TEXT $avp(text)\n");
xlog("DCS $avp(dcs)\n");
#!endif
// Construct a new SMS-Body:
$rpdata(all) = $null;
$rpdata(type) = 1; // RP-DATA: Network to UE
$rpdata(reference) = $avp(id);
$rpdata(originator) = $avp(from);
$tpdu(type) = 4; // SMS-Deliver
$tpdu(origen) = $avp(from); // The Destination becomes the originator of the SMS
$tpdu(payload) = $avp(text);
$tpdu(coding) = $avp(dcs);
$uac_req(method) = "MESSAGE";
$uac_req(ruri) = "sip:"+$avp(to)+"@"+DOMAIN;
$uac_req(furi) = "sip:"+SMSC_SERVER;
$uac_req(turi) = "sip:"+$avp(to)+"@"+DOMAIN;
$uac_req(hdrs) = "Content-Type: application/vnd.3gpp.sms\r\nRequest-Disposition: no-fork\r\nAccept-Contact: *;+g.3gpp.smsip\r\nX-MSG-ID: "+$avp(id)+"\r\n";
$uac_req(body) = $smsbody;
$uac_req(evroute)=1;
uac_req_send();
# sql_query("sms", "delete from messages where id=$avp(id);");
}
######################################################################
# SMS to OTT-Handsets
######################################################################
route[SMS_TO_SIP] {
#!ifdef WITH_DEBUG
xlog("SMS to SIP/OTT\n");
xlog("-------------------------------------\n");
xlog("FROM $avp(from)\n");
xlog("TO $avp(to)\n");
xlog("TEXT $avp(text)\n");
#!endif
$uac_req(method) = "MESSAGE";
$uac_req(ruri) = "sip:"+$avp(to)+"@"+DOMAIN;
$uac_req(furi) = "sip:+"+$avp(from)+"@"+DOMAIN;
$uac_req(turi) = "sip:"+$avp(to)+"@"+DOMAIN;
$uac_req(hdrs) = "Content-Type: text/plain\r\nX-MSG-ID: "+$avp(id)+"\r\n";
$uac_req(evroute)=1;
$uac_req(body) = $avp(text);
uac_req_send();
}
######################################################################
# SMS to Outbound
######################################################################
route[SMS_TO_OUTBOUND] {
#!ifdef WITH_DEBUG
xlog("SMS to Outbound\n");
xlog("-------------------------------------\n");
xlog("FROM $avp(from)\n");
xlog("TO $avp(to)\n");
xlog("TEXT $avp(text)\n");
#!endif
if ($avp(from_outbound) == 1) {
xlog("Not sending: FROM and TO Outbound!\n");
return 1;
exit;
}
if ($avp(from) == "494046895124")
$avp(from) = "491771782261";
if ($avp(from) == "494034927220")
$avp(from) = "491771782319";
http_client_query("https://rest.nexmo.com/sms/json?api_key=NEXMO_APIKEY&api_secret=NEXMO_APISECRET&from=$avp(from)&to=$avp(to)&text=$(avp(text){s.escape.user})", "$var(result)");
if ($retcode != 200) return -1;
json_get_field("$var(result)", "messages", "$var(messages)");
json_get_field("$var(messages)", "status", "$var(status)");
if ($var(status) != 0) return -1;
return 1;
}
######################################################################
# SMS Handling
######################################################################
route[SMS] {
#!ifdef WITH_DEBUG
xlog("SMS-Task\n");
xlog("-------------------------------------\n");
xlog("FROM $avp(from)\n");
xlog("TO $avp(to)\n");
xlog("TEXT $avp(text)\n");
xlog("DCS $avp(dcs)\n");
#!endif
# Query ENUM: Local number?
$var(enum) = "+"+$avp(to);
if (!enum_pv_query("$var(enum)")) {
route(SMS_TO_OUTBOUND);
return $retcode;
}
if (sql_query("sms", "insert into messages (caller, callee, text, dcs, valid) values ('$(avp(from){s.escape.common})', '$(avp(to){s.escape.common})', '$(avp(text){s.escape.common})', $avp(dcs), now());"))
return 1;
else
return -1;
}
######################################################################
# SMS Handling
######################################################################
route[SMS_WORKER] {
sql_query("sms", "select id, caller, callee, text, dcs from messages;", "q");
if ($dbr(q=>rows) > 0) {
$var(i) = 0;
while ($var(i) < $dbr(q=>rows)) {
if ($sht(sms_retries=>$dbr(q=>[$var(i),0])) == $null) {
$sht(sms_retries=>$dbr(q=>[$var(i),0])) = 0;
} else {
$sht(sms_retries=>$dbr(q=>[$var(i),0])) = $sht(sms_retries=>$dbr(q=>[$var(i),0])) + 1;
}
if ($sht(sms_retries=>$dbr(q=>[$var(i),0])) > 2) {
xlog("Dropping SMS [$dbr(q=>[$var(i),3])] TO $dbr(q=>[$var(i),2]) after 2 retries \n");
sql_query("sms", "delete from messages where id=$dbr(q=>[$var(i),0]);");
$sht(sms_retries=>$dbr(q=>[$var(i),0])) = $null;
} else {
$avp(id) = $dbr(q=>[$var(i),0]);
$avp(from) = $dbr(q=>[$var(i),1]);
$avp(to) = $dbr(q=>[$var(i),2]);
$avp(text) = $dbr(q=>[$var(i),3]);
$avp(dcs) = $dbr(q=>[$var(i),4]);
route(SEND_SMS);
#!ifdef WITH_DEBUG
xlog("ID $avp(id)\n");
xlog("FROM $avp(from)\n");
xlog("TO $avp(to)\n");
xlog("TEXT $avp(text)\n");
xlog("DCS $avp(dcs)\n");
#!endif
}
$var(i) = $var(i) + 1;
}
}
sql_result_free("q");
}
route[NOTIFY] {
if (has_body("application/reginfo+xml")) {
if (reginfo_handle_notify("location"))
send_reply("202", "Accepted");
} else {
send_reply("503", "Invalid Content-Type");
}
exit;
}
route[SEND_SMS] {
$var(uri) = "sip:"+$avp(to)+"@"+DOMAIN;
if (reg_fetch_contacts("location", "$var(uri)", "caller")) {
$var(j) = 0;
$var(is3gpp) = 0;
while($var(j) < $(ulc(caller=>count))) {
$var(k) = 0;
while($var(k) < $(ulc(caller=>addr)[$var(j)]{param.count})) {
if ($(ulc(caller=>addr)[$var(j)]{param.name,$var(k)}) == "+g.3gpp.smsip")
$var(is3gpp) = 1;
$var(k) = $var(k) + 1;
}
if ($var(is3gpp) == 1)
route(SMS_TO_3GPP);
else
route(SMS_TO_SIP);
$var(j) = $var(j) + 1;
}
} else {
if ($sht(publish_sent=>$var(uri)) == $null) {
reginfo_subscribe("$var(uri)", "SUBSCRIBE_EXPIRE");
$sht(publish_sent=>$var(uri)) = 1;
}
}
}
event_route [tm:local-request] {
if (is_method("SUBSCRIBE")) {
append_hf("P-Asserted-Identity: $ru\r\n");
}
}
event_route[uac:reply] {
if (($uac_req(evtype) == 1) && ($uac_req(evcode) == 200) && ($uac_req(hdrs) != $null) && ($uac_req(hdrs) != "")) {
$var(msgid) = $(uac_req(hdrs){line.sw,X-MSG-ID:}{s.substr,10,0}{s.int});
sql_query("sms", "delete from messages where id=$var(msgid);");
}
}