Dear ALL:
I think it is a very good chance to study Paul's ser.cfg file.
I use the 0.9.0 sample cfg and try to implement a call forward, busy
forward, no answer forward function.
But I got a 503 message when I use make a call from UA 1011 to UA
1022(registed on the same ser) with callforward to a PSTN .
But I have no voicemail option supported. So I must modify it.
In usr_preferences table:
username domain attribute value
-------------------------------------------------------------------------------------------------------------------
1022 ser.xxx.net.tw donotdisturb n
1022 ser.xxx.net.tw voicemail n
1022 ser.xxx.net.tw anoncallrej n
1022 ser.xxx.net.tw callidblock n
1022 ser.xxx.net.tw callfwd
0939749xxx(a)ser.xxx.net.tw
1022 ser.xxx.net.tw fwdnoanswer 0939749xxx(a)ser.xxx.net.tw
1022 ser.xxx.net.tw fwdbusy
0939749xxx(a)ser.xxx.net.tw
In grp table:
username domain grp
---------------------------------------------------
1022 ser.xxx.net.tw int
1011 ser.xxx.net.tw int
I don't know where to defind the 'dom' and 'int' or '-' setting at DB table.
What is its table name?
domain ==> ser.xxx.net.tw (the same as caller and machine)
When I test this call forward, a UA 1011 call to 1022. It
It should be forward to a PSTN and use route(3) or route(6).
But when I do it, it seems failed at lookup("aliases") and
lookup("location") function.
Log list below:
---------------------------------------------------------------------------------------------------------
ser /usr/local/sbin/ser[9232]: SER: BLIND CALL FORWARDING
ser /usr/local/sbin/ser[9232]: SER: Check Forwarding Number Rules
ser /usr/local/sbin/ser[9232]: SER: Look aliases
ser /usr/local/sbin/ser[9232]: ERROR: parse_uri: bad uri, state 0
parsed: <0939> (4) / <0939749xxx(a)ser.xxx.net.tw> (27)
ser /usr/local/sbin/ser[9232]: extract_aor(): Error while parsing
Address of Record
ser /usr/local/sbin/ser[9232]: lookup(): Error while extracting
address of record
ser /usr/local/sbin/ser[9232]: SER: Look location
ser /usr/local/sbin/ser[9232]: ERROR: parse_uri: bad uri, state 0
parsed: <0939> (4) / <0939749xxx(a)ser.xxx.net.tw> (27)
ser /usr/local/sbin/ser[9232]: extract_aor(): Error while parsing
Address of Record
ser /usr/local/sbin/ser[9232]: lookup(): Error while extracting
address of record
ser /usr/local/sbin/ser[9232]: SER: 503 Service Unavailable
---------------------------------------------------------------------------------------------------------
If I delete the record callfwd of 1022 and want to test call noanswer forward.
It seems can not forward to a PSTN number and jump to route(3) or route(6).
It always keep the orginial rule and use route(2).
Also the error message "error: mediaproxy/sendMediaproxyCommand():
can't connect to MediaProxy" always displays at log file whether the
call is connected or failed call.
Log list below:
---------------------------------------------------------------------------------------------------------ser
/usr/local/sbin/ser[9233]: SER: BLIND CALL FORWARDING
ser /usr/local/sbin/ser[9233]: SER: Look aliases
ser /usr/local/sbin/ser[9233]: SER: Look location
ser /usr/local/sbin/ser[9233]: SER isflagset (sip)
ser /usr/local/sbin/ser[9233]: SER: Look aliases
ser /usr/local/sbin/ser[9233]: SER: Look location
ser /usr/local/sbin/ser[9233]: SER isflagset (sip)
ser /usr/local/sbin/ser[9233]: SER: SIP Call On-Net section route(2)
ser /usr/local/sbin/ser[9233]: error:
mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy
ser /usr/local/sbin/ser[9231]: error:
mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy
ser /usr/local/sbin/ser[9231]: SER: SIP Call On-Net section route(2)
ser /usr/local/sbin/ser[9234]: SER: Failure Route section failure_route(1)
ser /usr/local/sbin/ser[9234]: SER: fork to fwdnoanswer
ser /usr/local/sbin/ser[9234]: SER: No Answer Failure and Jump to route(2)
ser /usr/local/sbin/ser[9234]: SER: SIP Call On-Net section route(2)
ser /usr/local/sbin/ser[9234]: ERROR: parse_uri: bad uri, state 0
parsed: <0939> (4) / <0939749xxx(a)ser.xxx.net.tw> (27)
ser /usr/local/sbin/ser[9234]: ERROR: parse_sip_msg_uri: bad uri
<0939749xxx(a)ser.xxx.net.tw>
ser /usr/local/sbin/ser[9234]: error:
mediaproxy/getDestinationDomain(): error parsing destination URI
ser /usr/local/sbin/ser[9234]: ERROR: parse_uri: bad uri, state 0
parsed: <0939> (4) / <0939749xxx(a)ser.xxx.net.tw> (27)
ser /usr/local/sbin/ser[9234]: ERROR: parse_sip_msg_uri: bad uri
<0939749xxx(a)ser.xxx.net.tw>
ser /usr/local/sbin/ser[9234]: is_uri_host_local(): Error while parsing URI
ser /usr/local/sbin/ser[9234]: error:
mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy
ser /usr/local/sbin/ser[9234]: ERROR: parse_uri: bad uri, state 0
parsed: <0939> (4) / <0939749xxx(a)ser.xxx.net.tw> (27)
ser /usr/local/sbin/ser[9234]: ERROR: uri2proxy: bad_uri:
0939749xxx(a)ser.xxx.net.tw
ser /usr/local/sbin/ser[9234]: ERROR: t_forward_nonack: failure to add branches
ser /usr/local/sbin/ser[9234]: ERROR: w_t_relay (failure mode):
forwarding failed
ser /usr/local/sbin/ser[9234]: error:
mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy
ser /usr/local/sbin/ser[9234]: ERROR: sl_reply_error used: I'm
terribly sorry, server error occurred (1/SL)
ser /usr/local/sbin/ser[9231]: SER: SIP Call On-Net section route(2)
---------------------------------------------------------------------------------------------------------
My ser.cfg list below:
---------------------------------------------------------------------------------------------------------
#
# $Id: ser.cfg,v 1.25 2004/11/30 16:28:24 andrei Exp $
#
# simple quick-start config script
#
# ----------- global configuration parameters ------------------------
debug=10 # debug level (cmd line: -dddddddddd)
fork=yes
log_stderror=no # (cmd line: -E)
/* Uncomment these lines to enter debugging mode
fork=no
log_stderror=yes
*/
listen=99.99.99.99
alias=ser.xxx.net.tw
alias=ser
alias=99.99.99.99
check_via=no # (cmd. line: -v)
dns=no # (cmd. line: -r)
rev_dns=no # (cmd. line: -R)
port=5060
children=4
fifo_mode=0666
fifo="/tmp/ser_fifo"
fifo_db_url="mysql://ser:heslo@localhost/ser"
# ------------------ module loading ----------------------------------
# Uncomment this if you want to use SQL database
loadmodule "/usr/local/lib/ser/modules/mysql.so"
loadmodule "/usr/local/lib/ser/modules/sl.so"
loadmodule "/usr/local/lib/ser/modules/tm.so"
loadmodule "/usr/local/lib/ser/modules/rr.so"
loadmodule "/usr/local/lib/ser/modules/maxfwd.so"
loadmodule "/usr/local/lib/ser/modules/usrloc.so"
loadmodule "/usr/local/lib/ser/modules/registrar.so"
loadmodule "/usr/local/lib/ser/modules/textops.so"
loadmodule "/usr/local/lib/ser/modules/auth.so"
loadmodule "/usr/local/lib/ser/modules/auth_db.so"
loadmodule "/usr/local/lib/ser/modules/exec.so"
loadmodule "/usr/local/lib/ser/modules/avpops.so"
loadmodule "/usr/local/lib/ser/modules/domain.so"
loadmodule "/usr/local/lib/ser/modules/group.so"
loadmodule "/usr/local/lib/ser/modules/uri.so"
loadmodule "/usr/local/lib/ser/modules/uri_db.so"
loadmodule "/usr/local/lib/ser/modules/permissions.so"
loadmodule "/usr/local/lib/ser/modules/speeddial.so"
loadmodule "/usr/local/lib/ser/modules/acc.so"
loadmodule "/usr/local/lib/ser/modules/pdt.so"
loadmodule "/usr/local/lib/ser/modules/options.so"
loadmodule "/usr/local/lib/ser/modules/mediaproxy.so"
loadmodule "/usr/local/lib/ser/modules/xlog.so"
# ----------------- setting module-specific parameters ---------------
# -- mediaproxy params --
modparam("mediaproxy", "natping_interval", 30)
modparam("mediaproxy", "sip_asymmetrics",
"/usr/local/etc/ser/sip-asymmetric-clients")
modparam("mediaproxy", "rtp_asymmetrics",
"/usr/local/etc/ser/rtp-asymmetric-clients")
# -- usrloc params --
#
# 0 = disable
# 1 = write-through
# 2 = write-back
#
modparam("usrloc", "db_mode", 1)
modparam("usrloc", "timer_interval", 60)
modparam("usrloc", "desc_time_order", 1)
# -- auth params --
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
# -- rr params --
# add value to ;lr param to make some broken UAs happy
modparam("rr", "enable_full_lr", 1)
# -- db_url params --
modparam("acc|auth_db|domain|group|permissions|speeddial|uri_db|usrloc|pdt",
"db_url", "mysql://ser:heslo@localhost/ser")
# -- use_domain params --
modparam("auth_db|group|registrar|speeddial|uri_db|usrloc", "use_domain", 0)
# -- permissions params --
modparam("permissions", "db_mode", 1)
modparam("permissions", "trusted_table", "trusted")
# -- accounting params --
modparam("acc", "db_flag", 1)
modparam("acc", "db_missed_flag", 1)
modparam("acc", "log_fmt", "cdfimorstup")
modparam("acc", "log_level", 1)
modparam("acc", "failed_transactions", 1)
modparam("acc", "report_cancels", 1)
modparam("acc", "report_ack", 0)
# -- domain params --
modparam("domain", "db_mode", 1)
# ------------- exec parameters
modparam("exec", "setvars", 1)
modparam("exec", "time_to_kill", 10)
# -- registration params --
modparam("registrar", "nat_flag", 2)
modparam("registrar", "min_expires", 60)
modparam("registrar", "max_expires", 86400)
modparam("registrar", "default_expires", 3600)
modparam("registrar", "append_branches", 1)
# -- avp params --
modparam("avpops", "avp_url", "mysql://ser:heslo@localhost/ser")
modparam("avpops", "avp_table", "usr_preferences")
#modparam("avpops", "use_domain", "1")
modparam("avpops", "uuid_column", "uuid")
modparam("avpops", "username_column", "username")
modparam("avpops", "domain_column", "domain")
modparam("avpops", "attribute_column", "attribute")
modparam("avpops", "value_column", "value")
modparam("avpops", "type_column", "type")
modparam("avpops", "avp_aliases",
"voicemail=i:500;calltype=i:700;fwd_no_answer_type=i:701;fwd_busy_type=i:702")
# To use more than one tables example
#modparam("avpops", "db_scheme",
"scheme1:table=subscriber;uuid_column=uuid;value_column=first_name")
# -- tm params --
modparam("tm", "fr_timer", 15)
modparam("tm", "fr_inv_timer", 22)
modparam("tm", "wt_timer", 5)
modparam("tm", "fr_inv_timer_avp", "inv_timeout")
# -- pdt params --
modparam("pdt", "db_table", "prefix_domain")
modparam("pdt", "prefix", "")
modparam("pdt", "hsize_2pow", 2)
modparam("pdt", "sync_time", 300)
modparam("pdt", "clean_time", 600)
# -- logging params
modparam("xlog", "buf_size", 8192)
# -- group params --
modparam("group", "table", "grp")
modparam("group", "user_column", "username")
modparam("group", "domain_column", "domain")
modparam("group", "group_column", "grp")
# -- speeddial params --
modparam("speeddial", "user_column", "username")
modparam("speeddial", "domain_column", "domain")
modparam("speeddial", "sd_user_column", "username_from_req_uri")
modparam("speeddial", "sd_domain_column", "domain_from_req_uri")
modparam("speeddial", "new_uri_column", "new_request_uri")
modparam("speeddial", "domain_prefix", "tel")
# ------------------------- request routing logic -------------------
# main routing logic
route {
# ------------------------------------------------------------------------
# Sanity Check Section
# ------------------------------------------------------------------------
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483", "Too Many Hops");
break;
};
if (msg:len > max_len) {
sl_send_reply("513", "Message Overflow");
break;
};
# ------------------------------------------------------------------------
# NOTIFY Keep-Alive Section
# ------------------------------------------------------------------------
if ((method=="NOTIFY") && search("^Event: keep-alive")) {
sl_send_reply("200", "OK");
break;
};
# ------------------------------------------------------------------------
# OPTIONS Section
# ------------------------------------------------------------------------
if (method=="OPTIONS") {
options_reply();
break;
};
# ------------------------------------------------------------------------
# NAT Test Section #1
# ------------------------------------------------------------------------
if (method=="REGISTER" && client_nat_test("3")) {
fix_contact();
force_rport();
setflag(2);
};
# ------------------------------------------------------------------------
# Click2Dial Section # 14
# ------------------------------------------------------------------------
#if (src_ip=="99.99.99.99" && (search("^From: <sip:700@") ||
search("^To: <sip:700@"))) {
# setflag(14);
#};
# ------------------------------------------------------------------------
# Registration Section
# ------------------------------------------------------------------------
if (method=="REGISTER") {
# allow all requests from user 700 - the Click2Dial controller
if (!isflagset(14)) {
if (!is_from_local()) {
sl_send_reply("403", "Unknown Domain");
break;
};
if (!www_authorize("", "subscriber")) {
www_challenge("", "0");
break;
};
if (!check_to()) {
sl_send_reply("401", "Unauthorized");
break;
};
# To - Use To username and (optionally) domain to check
if (is_user_in("To", "demo-disabled")) {
sl_send_reply("403", "Your evaluation
period has expired");
break;
};
# To - Use To username and (optionally) domain to check
if (is_user_in("To", "disabled")) {
sl_send_reply("403", "Your account has
been disabled");
break;
};
};
# snom sip phones use this header to start their
# keep-alive mechanism for NAT bindings
append_to_reply("P-NAT-Refresh: 15\r\n");
if (!save("location")) {
sl_reply_error();
};
break;
};
# ------------------------------------------------------------------------
# Accounting Section # 1
#
# NOTE: We test for flag 14 because we do not want to record Click2Dial
# entries
# ------------------------------------------------------------------------
if ((method=="INVITE" || method=="BYE") && !isflagset(14)) {
setflag(1);
};
# ------------------------------------------------------------------------
# NAT Tear-Down Section
# ------------------------------------------------------------------------
if ((method == "BYE" || method == "CANCEL")) {
end_media_session();
};
# ------------------------------------------------------------------------
# Record Route Section
#
# we record-route all messages -- to make sure that subsequent messages
# will go through our proxy; that's particularly good if upstream and
# downstream entities use different transport protocol
# ------------------------------------------------------------------------
if (!method=="REGISTER") {
record_route();
};
# ------------------------------------------------------------------------
# Loose Route Section
#
# Grant route routing if route headers present
# ------------------------------------------------------------------------
if (loose_route()) {
route(2);
break;
};
# ------------------------------------------------------------------------
# Message Waiting Indicator SUBSCRIBE Section
#
# Make sure all SUBSCRIBE messages with header "Event: message-summary"
# are sent to the voicemail server
# ------------------------------------------------------------------------
#if ((method=="SUBSCRIBE") && search("^Event: message-summary")) {
# rewritehostport("99.99.99.100:5060");
# t_relay();
# break;
#};
# ------------------------------------------------------------------------
# NAT Test Section #1
# ------------------------------------------------------------------------
if (client_nat_test("3") && !search("^Record-Route:")) {
force_rport();
fix_contact();
};
# ------------------------------------------------------------------------
# Enhanced Voicemail Applications Section
#
# Access additional Asterisk applications at extension 701 and 702
# ------------------------------------------------------------------------
#if (uri=~"^sip:70[1|2]@") {
# route(5);
# break;
#};
# ------------------------------------------------------------------------
# PSTN Section
# ------------------------------------------------------------------------
#
# This is an example of US phone call.
#
#if (method=="INVITE") {
# if (uri=~"^sip:1[0-9]{10}@") {
# strip(1);
# };
# if ((uri=~"^sip:911@.*") || (uri=~"^sip:900[0-9]{7}@") ||
(uri=~"^sip:976[0-9]{7}@")) {
# sl_send_reply("503", "Service Unavailable");
# break;
# };
#};
if (method=="INVITE") { ## Deny PSTN to 0204 and 095 of Taiwan
if ((uri=~"^sip:0204[0-9]*@") || (uri=~"^sip:095[0-9]*@")) {
sl_send_reply("503", "Service Unavailable");
break;
};
};
# ------------------------------------------------------------------------
# Alias Routing Section
# ------------------------------------------------------------------------
lookup("aliases");
if (!uri==myself) {
route(2);
break;
};
# ------------------------------------------------------------------------
# Load ACL Section
# ------------------------------------------------------------------------
if (method=="INVITE" && !isflagset(14)) {
xlog("L_ERR", "Time:[%Tf] Method:<%rm> r-uri:<%ru>\n");
xlog("L_ERR", "IP:<%is> From:<%fu> To:<%tu> %ct\n");
if (is_user_in("Request-URI", "voicemail")) {
setflag(31);
};
if (is_from_local() || is_uri_host_local()) {
#if (is_user_in("From", "411")) {
# setflag(30); ## some call from
directory service
#};
# Check user from grp table
if (is_user_in("From", "int")) {
# log(1, "SER: a INT user\n");
setflag(29);
};
if (is_user_in("From", "free-pstn")) {
# log(1, "SER: a FREE-PSTN user\n");
setflag(28);
};
if (avp_db_load("$from/username", "s:callidblock")) {
if (avp_check("s:callidblock", "eq/y/i")) {
setflag(25);
};
};
};
if (avp_db_load("$ruri/username", "s:anoncallrej")) {
if (avp_check("s:anoncallrej", "eq/y/i")) {
log(1, "SER: a ANON-CALL-REJ user\n");
setflag(24);
};
};
};
# ------------------------------------------------------------------------
# Anonymous Call Rejection Section # 24
# ------------------------------------------------------------------------
if (isflagset(24) && (method=="INVITE") &&
search("^(f|F)rom:.*(a|A)nonymous")) {
route(8);
break;
};
# ------------------------------------------------------------------------
# 411 Directory Assistance Section # 30
# ------------------------------------------------------------------------
#if (method=="INVITE" && uri=~"^sip:411@.*") {
# if (isflagset(30)) {
# avp_write("$from", "i:34");
# avp_pushto("$ruri", "i:34");
# strip_tail(7);
# subst_uri('/^sip:([0-9]+)@(.*)$/sip:\15551212@\2/i');
# avp_delete("i:34");
# route(3);
# break;
# };
# sl_send_reply("503", "Service Unavailable");
# break;
#};
# ------------------------------------------------------------------------
# Speed Dialing Section
# ------------------------------------------------------------------------
if ((method=="INVITE") && (uri=~"^sip:[0-9]{2}@.*")) {
sd_lookup("speed_dial");
};
# ------------------------------------------------------------------------
# 011 International Call Section # 29
# ------------------------------------------------------------------------
#if (method=="INVITE" && uri=~"^sip:011[0-9]*@") {
# if (isflagset(29)) {
# route(6);
# } else {
# sl_send_reply("503", "Service Unavailable");
# };
# break;
#};
# ------------------------------------------------------------------------
# 002 International Call Section # 29
# ------------------------------------------------------------------------
if (method=="INVITE" && uri=~"^sip:002[0-9]*@") {
if (isflagset(29)) {
log(1, "SER: an International Call route(6)\n");
route(6);
} else {
sl_send_reply("503", "Service Unavailable");
};
break;
};
# ------------------------------------------------------------------------
# 0XXXXXXXXX Domestic Call Section # 29
# ------------------------------------------------------------------------
if (method=="INVITE" && uri=~"^sip:0[0-9]{9}@") {
if (isflagset(29)) {
log(1, "SER: a Domestic Call route(6)\n");
route(6);
} else {
sl_send_reply("503", "Service Unavailable");
};
break;
};
# ------------------------------------------------------------------------
# URI Compare Section
#
# Here we compare the "from" and "to" to see if the caller is dialing
# their own extension. If so then we route to voicemail(31) if needed
# ------------------------------------------------------------------------
if (method=="INVITE") {
avp_write("$from", "i:34");
if (avp_check("i:34", "eq/$ruri/i")) {
if (isflagset(31)) {
route(5);
break;
} else {
sl_send_reply("486", "Busy");
break;
};
};
};
# ------------------------------------------------------------------------
# Call Block Section
# ------------------------------------------------------------------------
#if (is_caller_blocked()) {
# route(7);
# break;
#};
# ------------------------------------------------------------------------
# Do Not Disturb Section
# ------------------------------------------------------------------------
if (avp_db_load("$ruri/username", "s:donotdisturb")) {
if (avp_check("s:donotdisturb", "eq/y/i")) {
route(5);
break;
};
};
# ------------------------------------------------------------------------
# Blind Call Forwarding Section
# ------------------------------------------------------------------------
if (method=="INVITE") {
log(1, "SER: BLIND CALL FORWARDING\n");
# here we must store the current (aka original) R-URI because if
# we set call forwarding and the forwarded number is busy then we
# need to use this original R-URI to determine which voicemail
# box we should go to
if (isflagset(31)) {
avp_write("$ruri", "$voicemail");
};
if (avp_db_load("$ruri/username", "s:callfwd")) {
avp_pushto("$ruri", "s:callfwd");
# lookup the call fowarding number to see if it
is a served
# sip number or a PSTN number
# check forwarding number rules
log(1, "SER: Check Forwarding Number Rules\n");
route(1);
if (avp_check("$calltype", "eq/-/i")) {
log(1, "SER: 503 Service Unavailable\n");
sl_send_reply("503", "Service Unavailable");
break;
};
# test for domestic PSTN gateway
if (avp_check("$calltype", "eq/dom/i")) {
log(1, "SER: Start a domestic PSTN call route(3)\n");
route(3);
break;
};
# test for international PSTN gateway
if (avp_check("$calltype", "eq/int/i")) {
log(1, "SER: Start an international
PSTN call route(6)\n");
route(6);
break;
};
};
};
# ------------------------------------------------------------------------
# Call Routing Section
# ------------------------------------------------------------------------
if (!lookup("location")) {
# if flag 31 (ie voicemail) is set and we made it here this means
# the user's phone is not registered anywhere. We'll forward to
# voicemail after this block because we need to check the call
# forward settings first
if (isflagset(31)) {
# flag 19 means the user has voicemail but is not online
# so we need to remember to send to voicemail if call
# forwarding is not enabled
setflag(19);
};
if (method=="INVITE") {
if (does_uri_exist()) {
# subscriber record found, but they're offline
log(1, "SER: Temporarily Unavailable\n");
sl_send_reply("480", "Temporarily Unavailable");
break;
};
if (uri=~"^sip:0[0-9]{9}@") {
# Send to PSTN Gateway
if (isflagset(28)) {
log(1, "SER: Start a PSTN call\n");
route(3);
} else {
log(1, "SER: 503 Service Unavailable\n");
sl_send_reply("503", "Service
Unavailable");
};
break;
};
sl_send_reply("404", "User Not Found");
break;
};
};
# ------------------------------------------------------------------------
# Call Forwarding Section
# ------------------------------------------------------------------------
if (method=="INVITE") {
# save R-URI in a temp AVP for later use
avp_write("$ruri", "i:99");
# only load the forward no answer option if voice mail
is not enabled
if (!isflagset(31)) {
if (avp_db_load("$ruri/username", "s:fwdnoanswer")) {
route(1);
if (!avp_check("$calltype", "eq/-/i")) {
if (avp_check("$calltype", "eq/dom/i")) {
avp_write("dom",
"$fwd_no_answer_type");
} else if
(avp_check("$calltype", "eq/int/i")) {
avp_write("int",
"$fwd_no_answer_type");
} else {
avp_write("sip",
"$fwd_no_answer_type");
}
setflag(27);
};
};
};
if (avp_db_load("$ruri/username", "s:fwdbusy")) {
route(1);
if (!avp_check("$calltype", "eq/-/i")) {
if (avp_check("$calltype", "eq/dom/i")) {
avp_write("dom", "$fwd_busy_type");
} else if (avp_check("$calltype", "eq/int/i")) {
avp_write("int", "$fwd_busy_type");
} else {
avp_write("sip", "$fwd_busy_type");
}
setflag(26);
};
};
avp_pushto("$ruri", "i:99");
};
if (isflagset(19)) {
# send to voicemail
route(5);
} else {
route(2);
};
}
route[1] {
# Here we have route checks for all the call forwarding stuff.
# The return values are passed as AVP $calltype as follows:
#
# "-" = R-URI is not allowed
# "dom" = R-RURI is a domestic call
# "int" = R-RURI is an international call
# "sip" = R-RURI is a sip call
avp_write("-", "$calltype");
# US international call
#if (uri=~"^sip:1[0-9]{10}@") {
# strip(1);
#};
# Call rejected
#if ((uri=~"^sip:70[1|2]@") || (uri=~"^sip:411@.*") ||
# (uri=~"^sip:911@.*") || (uri=~"^sip:900[0-9]{7}@") ||
# (uri=~"^sip:976[0-9]{7}@")) {
# break;
#};
if ((uri=~"^sip:0204[0-9]*@") ||
(uri=~"^sip:095[0-9]*@") ||
(uri=~"^sip:[0-9]{3}@")) {
break;
};
# Error Message from this <================== ERROR
log(1, "SER: Look aliases\n");
lookup("aliases");
log(1, "SER: Look location\n");
if (!lookup("location")) {
if (uri=~"^sip:0[0-9]{9}@") {
# test for domestic PSTN number
if (isflagset(28)) {
log(1, "SER isflagset 28 (domestic)\n");
avp_write("dom", "$calltype");
};
# } else if (uri=~"^sip:011[0-9]*@") {
} else if (uri=~"^sip:002[0-9]*@") {
# test for international PSTN number
if (isflagset(29)) {
log(1, "SER isflagset 29 (int)\n");
avp_write("int", "$calltype");
};
};
break;
};
log(1, "SER isflagset (sip)\n");
avp_write("sip", "$calltype");
}
route[2] {
log(1, "SER: SIP Call On-Net section route(2)\n");
if ((method=="INVITE") && !allow_trusted()) {
if (!proxy_authorize("", "subscriber")) {
proxy_challenge("", "0");
break;
} else if (!check_from()) {
log(1, "Spoofed SIP call attempt");
sl_send_reply("403", "Use From=ID");
break;
} else if (!(is_from_local() || is_uri_host_local())) {
sl_send_reply("403", "Please register to use
our service");
break;
};
};
if (uri=~"[@:](192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)" &&
!search("^Route:")){
sl_send_reply("479", "We don't forward to private IP addresses");
break;
};
if (isflagset(25)) {
replace("^From:(.*)>" , "From: \"Anonymous\"
<sip:someone@anonymous.invalid>");
};
if (method=="INVITE" || method=="ACK") {
use_media_proxy();
};
t_on_failure("1");
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
route[3] {
log(1, "SER: Demestic Call Off-Net section route(3)\n");
# All Domestic Calls Go To CISCO 5300
if (method=="INVITE") {
if (!proxy_authorize("", "subscriber")) {
proxy_challenge("", "0");
break;
} else if (!check_from()) {
log(1, "Spoofed SIP call attempt");
sl_send_reply("403", "Use From=ID");
break;
} else if (!(is_from_local() || is_uri_host_local())) {
sl_send_reply("403", "Please register to use
our service");
break;
};
# enable caller id blocking for PSTN calls
if (isflagset(25)) {
append_rpid_hf();
};
};
# SIP->PSTN calls get 45 seconds to timeout
avp_write("i:45", "inv_timeout");
rewritehost("99.99.99.250");
if (uri=~"[@:](192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)" &&
!search("^Route:")){
sl_send_reply("479", "We don't forward to private IP addresses");
break;
};
if (method=="INVITE" || method=="ACK") {
use_media_proxy();
};
if (isflagset(31)) {
t_on_failure("1");
};
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
route[4] {
log(1, "SER: Voice Mail section route(4)\n");
# voicemail route #1
#
# this path this executed during these conditions:
#
# cond 1) the called number is in the location table
# but the callee did not answer the phone
# (ie, failover to voicemail)
if (isflagset(25)) {
replace("^From:(.*)>" , "From: \"Anonymous\"
<sip:someone@anonymous.invalid>");
};
rewritehostport("99.99.99.100:5060");
append_branch();
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
route[5] {
log(1, "SER: Voice Mail section route(5)\n");
# voicemail route #2
#
# this path this executed during these conditions:
#
# cond 1) the called number is not in the location table
# cond 2) the from_uri == to_uri (ie, caller==callee)
if (method=="INVITE" || method=="ACK") {
use_media_proxy();
};
rewritehostport("99.99.99.100:5060");
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
route[6] {
log(1, "SER: International Call Off-Net section route(6)\n");
# All International Calls Go To CISCO 5300
if (method=="INVITE") {
if (!proxy_authorize("", "subscriber")) {
proxy_challenge("", "0");
break;
} else if (!check_from()) {
log(1, "Spoofed SIP call attempt");
sl_send_reply("403", "Use From=ID");
break;
} else if (!(is_from_local() || is_uri_host_local())) {
sl_send_reply("403", "Please register to use
our service");
break;
};
# enable caller id blocking for PSTN calls
if (isflagset(25)) {
append_rpid_hf();
};
};
# SIP->PSTN calls get 45 seconds to timeout
avp_write("i:45", "inv_timeout");
rewritehost("99.99.99.240");
if (uri=~"[@:](192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)" &&
!search("^Route:")){
sl_send_reply("479", "We don't forward to private IP addresses");
break;
};
if (method=="INVITE" || method=="ACK") {
use_media_proxy();
};
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
route[7] {
log(1, "SER: Caller Blocked section route(7)\n");
# caller blocked announcment
#
# this path this executed if a caller has been blocked
if (method=="INVITE" || method=="ACK") {
use_media_proxy();
};
rewriteuri("sip:699@99.99.99.100:5060");
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
route[8] {
log(1, "SER: Anonymous Call Rejection section route(8)\n");
# anonymous call rejection announcment
#
# this path this executed for anonymous callers
if (method=="INVITE" || method=="ACK") {
use_media_proxy();
};
rewriteuri("sip:698@99.99.99.100:5060");
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
onreply_route[1] {
# Not all 2xx messages have a content body so here we
# make sure our Content-Length > 0 to avoid a parse error
if (status=~"(180)|(183)|2[0-9][0-9]") {
if (!search("^Content-Length:\ 0")) {
use_media_proxy();
};
};
if (client_nat_test("1")) {
fix_contact();
};
}
failure_route[1] {
log(1, "SER: Failure Route section failure_route(1)\n");
# if caller hung up then don't sent to voicemail
if (t_check_status("487")) {
break;
};
if (isflagset(26) && t_check_status("486")) {
# forward busy is flag 26
if (avp_pushto("$ruri", "s:fwdbusy")) {
log(1, "SER: fork to fwdbusy\n");
avp_delete("s:fwdbusy");
append_branch();
resetflag(26);
# test for domestic PSTN gateway
if (avp_check("$fwd_busy_type", "eq/dom/i")) {
# test for domestic PSTN gateway
log(1, "SER: Busy Failure and Jump to
route(3)\n");
route(3);
} else if (avp_check("$fwd_busy_type", "eq/int/i")) {
# test for international PSTN gateway
log(1, "SER: Busy Failure and Jump to
route(6)\n");
route(6);
} else {
# default to sip call
log(1, "SER: Busy Failure and Jump to
route(2)\n");
route(2);
};
break;
};
};
# here we can have either voicemail __OR__ forward no answer
if (isflagset(27) && t_check_status("408")) {
# forward no answer is flag 27
if (avp_pushto("$ruri", "s:fwdnoanswer")) {
log(1, "SER: fork to fwdnoanswer\n");
avp_delete("s:fwdnoanswer");
append_branch();
resetflag(27);
if (avp_check("$fwd_no_answer_type", "eq/dom/i")) {
# test for domestic PSTN gateway
log(1, "SER: No Answer Failure and Jump
to route(3)\n");
route(3);
} else if (avp_check("$fwd_no_answer_type",
"eq/int/i")) {
# test for international PSTN gateway
log(1, "SER: No Answer Failure and Jump
to route(6)\n");
route(6);
} else {
# default to sip call
log(1, "SER: No Answer Failure and Jump
to route(2)\n");
route(2);
};
break;
};
} else if (isflagset(31) && avp_pushto("$ruri", "$voicemail")) {
avp_delete("$voicemail");
log(1, "SER: No Answer Failure and Jump to route(4)\n");
route(4);
break;
};
}
Juha,
I have two gateways defined in the gw table and a have a few LCR rules
in the lcr table. The one lcr entry is a "catch-all" which would be
used if all other PSTN gateways failed.
My LCR table looks like this
'prefix','from_uri','grp_id','priority'
'321939','%321251%','1','2'
'407319','%321251%','1','2'
'%','%','2','1'
So if I dial from 3212518888 to 4073195555 then I would think at the
gateway in group #1 would be used first and if it failed then the
gateway in group #2 would be used.
However when next_gw() is called the following SQL is executed:
SELECT gw.ip_addr, gw.port
FROM gw, lcr
WHERE 'sip:3212518888@sip.mycompany.com' LIKE lcr.from_uri AND
'4073195555' LIKE CONCAT(lcr.prefix, '%') AND
lcr.grp_id = gw.grp_id
ORDER BY CHAR_LENGTH(lcr.prefix), lcr.priority DESC, RAND()
The ORDER BY clause causes the group #2 gateway to appear first in the
result set because '%' sorts before '407319'.
So should this SQL ORDER BY clause be changed to
ORDER BY CHAR_LENGTH(lcr.prefix) DESC, lcr.priority DESC, RAND()
or is there a better way to specify a "catch-all" gateway?
Regards,
Paul
Hello!
I'm implementing some VoIP system with SER+Asterisk. I've already
implemented many features, but all of them was tested only in non-NAT
environments. Now, at final-alpha stage (before starting massive beta
tests) I found big (as for me) problem with NAT... Now I need a working
example of ser.cfg (it will be really good) or, simply, to talk with
someone, who realized such scheme...
My current problem is with ua-to-ua calls between my users...
I have a following call routing scheme...
UA1->...->SER->Asterisk->SER->...->UA2...
Description: UA1 calls to some number, ser routes this call to asterisk,
asterisk resolves that number to some account (login name, that being
used by users to login to ser) and makes call to sip/ser/user_name...
and ser routes this call for user with such login...
I have strange problems with natted UAs...
Please, send me a working example of similiar schemes
(ser+asterisk+nat)... or help me by a word ;-)
Great thanks!
--
/Scoundrel
Basically what you do is to load the number to forward to by using
avp_db_load and then add code in failure_route to test on the return codes,
write the loaded number into ruri and use append_branch() to fork a new
request. Paul posted an example on serusers
http://lists.iptel.org/pipermail/serusers/2005-January/014807.html
He uses a more complex authorization structure for giving users access to
various types of calls (local, long distance, international), so you will
have to sort out the code necessary for the forwarding you want to do.
Here is what you need on failure_route[1] (remember to set t_on_failure[1]
before calling t_relay() ):
# flag 26 means that a "forward busy" number is set
# This flag is set if avp_db_load("$ruri","s:fwdbusy") resulted in a
an avpair being loaded (before t_relay())
# Code example using only username portion of ruri to look up avpair:
if (avp_db_load("$ruri/username", "s:fwdbusy")) { setflag(26) }
if (isflagset(26) && t_check_status("486")) {
# forward busy is flag 26
if (avp_pushto("$ruri", "s:fwdbusy")) {
avp_delete("s:fwdbusy");
append_branch();
resetflag(26);
# route the call to IP or PSTN
route(2);
break;
};
};
g-)
Charles Wang wrote:
> Thank you for your kind to answer me these question.
> And because I can't find a lot of discussions at serusers's maillist.
> So I post it to serdev. I am very sorry to do that.
>
> I have no voicemail solution in my scenario. But I wanna implement the
> call busy forward and noanswer forward to another UA or PSTN.
> For example: if A call B and B is busy or noanswer, then forward this
> call to C or PSTN(defined by B). Is it possible?
>
> Why does almost discussions about avpops are about voicemail?
> Is it mean that system will send a voicemail to
> "1011(a)domainA.com"(setting above at usr_preferences) if a UA is busy
> or noanswer?
>
> How can I implement it if I want to forward the busy call or noanswer
> call to PSTN or another UA(registed on the same machine)?
>
>
> On Sat, 19 Feb 2005 12:02:18 +0100, Greger V. Teigre
> <greger(a)teigre.com> wrote:
>> I don't think your message is appropriate for serdev, so I removed
>> it from the recipient list.
>> See inline comments.
>>
>> Charles Wang wrote:
>>> Dear ALL:
>>>
>>> I have defined these lines at my ser.cfg.
>>>
>>> modparam("avpops", "avp_url", "mysql://ser:heslo@localhost/ser")
>>> modparam("avpops", "avp_table", "usr_preferences")
>>> modparam("avpops", "uuid_column", "uuid")
>>> modparam("avpops", "username_column", "username")
>>> modparam("avpops", "domain_column", "domain")
>>> modparam("avpops", "attribute_column", "attribute")
>>> modparam("avpops", "value_column", "value")
>>> modparam("avpops", "type_column", "type")
>>> modparam("avpops", "avp_aliases",
>>> "voicemail=i:500;calltype=i:700;fwd_no_answer_type=i:701;fwd_busy_type=i:702")
>>>
>>> Q1: If I use usr_preferences as default table, should I insert some
>>> initial data to it?
>>> Can you give me some example?
>>
>> Yes, you should. Let's say you want user a(a)b.com to have voicemail
>> as an option. Add:
>>
>> username=a
>> domain=b.com
>> attribute=voicemail
>> value=y
>> type=0 (default string)
>>
>>>
>>> And I have refered to http://www.voice-system.ro/docs/avpops
>>>
>>> And find many examples in it.
>>>
>>> But I still can't understand what it mean about avp_db_load().
>>
>> avp_db_load() will load a certain value from your usr_preferences
>> table.
>>
>> avp_db_load("$ruri","s:voicemail");
>> will use to request uri (i.e. somebody is calling a(a)b.com) to lookup
>> the attribute voicemail. Instead of "$ruri", you can use
>> "$ruri/username" or "$ruri/domain" and only the username or domain
>> part of $ruri, respectively, will be used to look up the attribute
>> voicemail in the table. avp_check("s:voicemail", "eq/y/i") can then
>> be used to check if value from the usr_preferences table is "y".
>>
>>> my avp table is named as "usr_preferences" and it is empty before I
>>> use avpops modules.
>>>
>>> For this web page said:
>>> avp_db_load("$ruri/domain","i:/domain_preferences");
>>> - loads all AVPs with ID from 'domain_preferences'
>>> table for domain from RURI
>>> Q2: Is "$ruri" the caller user's URI? and the "domain" is the same?
>>
>> Yes.
>>
>>> Is "domain_preferences" table name?
>> Yes, you can opt to select a different table. It is not necessary
>> though.
>>
>>> Is it equal to my
>>> "usr_preferences"? Or it is just a virtual table in memory?
>> No and no.
>>
>> avpops is a very powerful module with various ways of using tables,
>> loading av pairs and doing tests. Remember that avpairs are no more
>> than pairs of attribute names (either string names as above or
>> integer values i:34) and values (either string values or integer
>> values). These avpairs must be loaded from somewhere, using
>> avp_db_load avp_radius_load, etc using $from or $ruri for looking up
>> the correct pair.
>>
>> g-)
hello
i try to make run a web application clik to dial via SER , the server
apache and SER is installed in to differents machines, but my programm
bloc , i m ussing serfifo to communicate with ser.
any help
thanks.
Dear ALL:
I have defined these lines at my ser.cfg.
modparam("avpops", "avp_url", "mysql://ser:heslo@localhost/ser")
modparam("avpops", "avp_table", "usr_preferences")
modparam("avpops", "uuid_column", "uuid")
modparam("avpops", "username_column", "username")
modparam("avpops", "domain_column", "domain")
modparam("avpops", "attribute_column", "attribute")
modparam("avpops", "value_column", "value")
modparam("avpops", "type_column", "type")
modparam("avpops", "avp_aliases",
"voicemail=i:500;calltype=i:700;fwd_no_answer_type=i:701;fwd_busy_type=i:702")
Q1: If I use usr_preferences as default table, should I insert some
initial data to it?
Can you give me some example?
Schema List below:
mysql> desc usr_preferences;
+-----------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| uuid | varchar(64) | | | | |
| username | varchar(100) | | PRI | | |
| domain | varchar(128) | | PRI | | |
| attribute | varchar(32) | | PRI | | |
| value | varchar(128) | | PRI | | |
| type | int(11) | | | 0 | |
| modified | timestamp(14) | YES | | NULL | |
+-----------+---------------+------+-----+---------+-------+
And I have refered to http://www.voice-system.ro/docs/avpops
And find many examples in it.
But I still can't understand what it mean about avp_db_load().
my avp table is named as "usr_preferences" and it is empty before I
use avpops modules.
For this web page said:
avp_db_load("$ruri/domain","i:/domain_preferences");
- loads all AVPs with ID from 'domain_preferences'
table for domain from RURI
Q2: Is "$ruri" the caller user's URI? and the "domain" is the same?
Is "domain_preferences" table name? Is it equal to my "usr_preferences"?
Or it is just a virtual table in memory?
Thank you for your answer my stupid questions.
Best Regard
Charles
Is there a way to log status codes in SER?
I would like to report the following types of info:
SIP/2.0 404 Not Found
SIP/2.0 200 OK
In addition perhaps the callerid, uri, etc.
:M
Dear ALL:
I build a ser and use a 0.9.0 example of ser.cfg.
Now I have some error message in my log during I make a call.
Feb 19 05:53:51 ser /usr/local/sbin/ser[3551]: SER: Load ACL
Feb 19 05:53:51 ser /usr/local/sbin/ser[3551]: SER: a INT user
Feb 19 05:53:51 ser /usr/local/sbin/ser[3549]: error:
mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy
Feb 19 05:53:51 ser /usr/local/sbin/ser[3551]: SER: a FREE-PSTN user
Feb 19 05:53:51 ser /usr/local/sbin/ser[3551]: error:
mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy
Feb 19 05:53:57 ser /usr/local/sbin/ser[3549]: error:
mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy
Feb 19 05:54:00 ser /usr/local/sbin/ser[3551]: error:
mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy
Feb 19 05:54:11 ser /usr/local/sbin/ser[3550]: error:
mediaproxy/sendMediaproxyCommand(): can't connect to MediaProxy
Thank you for your kind.
Best Regard
Charles
My ser.cfg list below:
#
# $Id: ser.cfg,v 1.25 2004/11/30 16:28:24 andrei Exp $
#
# simple quick-start config script
#
# ----------- global configuration parameters ------------------------
debug=10 # debug level (cmd line: -dddddddddd)
fork=yes
log_stderror=no # (cmd line: -E)
/* Uncomment these lines to enter debugging mode
fork=no
log_stderror=yes
*/
listen=61.220.190.248
alias=ser.xxx.net
alias=ser
alias=xx.xx.xx.xx
check_via=no # (cmd. line: -v)
dns=no # (cmd. line: -r)
rev_dns=no # (cmd. line: -R)
port=5060
children=4
fifo_mode=0666
fifo="/tmp/ser_fifo"
fifo_db_url="mysql://ser:heslo@localhost/ser"
# ------------------ module loading ----------------------------------
# Uncomment this if you want to use SQL database
loadmodule "/usr/local/lib/ser/modules/mysql.so"
loadmodule "/usr/local/lib/ser/modules/sl.so"
loadmodule "/usr/local/lib/ser/modules/tm.so"
loadmodule "/usr/local/lib/ser/modules/rr.so"
loadmodule "/usr/local/lib/ser/modules/maxfwd.so"
loadmodule "/usr/local/lib/ser/modules/usrloc.so"
loadmodule "/usr/local/lib/ser/modules/registrar.so"
loadmodule "/usr/local/lib/ser/modules/textops.so"
# Uncomment this if you want digest authentication
# mysql.so must be loaded !
loadmodule "/usr/local/lib/ser/modules/auth.so"
loadmodule "/usr/local/lib/ser/modules/auth_db.so"
loadmodule "/usr/local/lib/ser/modules/exec.so"
loadmodule "/usr/local/lib/ser/modules/avpops.so"
loadmodule "/usr/local/lib/ser/modules/domain.so"
loadmodule "/usr/local/lib/ser/modules/group.so"
loadmodule "/usr/local/lib/ser/modules/uri.so"
loadmodule "/usr/local/lib/ser/modules/uri_db.so"
loadmodule "/usr/local/lib/ser/modules/permissions.so"
loadmodule "/usr/local/lib/ser/modules/speeddial.so"
loadmodule "/usr/local/lib/ser/modules/acc.so"
loadmodule "/usr/local/lib/ser/modules/pdt.so"
loadmodule "/usr/local/lib/ser/modules/options.so"
loadmodule "/usr/local/lib/ser/modules/mediaproxy.so"
loadmodule "/usr/local/lib/ser/modules/xlog.so"
# ----------------- setting module-specific parameters ---------------
# -- mediaproxy params --
modparam("mediaproxy", "natping_interval", 30)
modparam("mediaproxy", "sip_asymmetrics",
"/usr/local/etc/ser/sip-asymmetric-clients")
modparam("mediaproxy", "rtp_asymmetrics",
"/usr/local/etc/ser/rtp-asymmetric-clients")
# -- usrloc params --
# Uncomment this if you want to use SQL database
# for persistent storage and comment the previous line
# ------------- usrloc parameters
# 0 = disable
# 1 = write-through
# 2 = write-back
modparam("usrloc", "db_mode", 1)
modparam("usrloc", "timer_interval", 60)
modparam("usrloc", "desc_time_order", 1)
# -- auth params --
# Uncomment if you are using auth module
#
modparam("auth_db", "calculate_ha1", yes)
#
# If you set "calculate_ha1" parameter to yes (which true in this config),
# uncomment also the following parameter)
#
modparam("auth_db", "password_column", "password")
# -- rr params --
# add value to ;lr param to make some broken UAs happy
modparam("rr", "enable_full_lr", 1)
# -- db_url params --
modparam("acc|auth_db|domain|group|permissions|speeddial|uri_db|usrloc|pdt",
"db_url", "mysql://ser:heslo@localhost/ser")
# -- use_domain params --
modparam("auth_db|group|registrar|speeddial|uri_db|usrloc", "use_domain", 0)
# -- permissions params --
modparam("permissions", "db_mode", 1)
modparam("permissions", "trusted_table", "trusted")
# -- accounting params --
modparam("acc", "db_flag", 1)
modparam("acc", "db_missed_flag", 1)
modparam("acc", "log_fmt", "cdfimorstup")
modparam("acc", "log_level", 1)
modparam("acc", "failed_transactions", 1)
modparam("acc", "report_cancels", 1)
modparam("acc", "report_ack", 0)
# -- domain params --
modparam("domain", "db_mode", 1)
# ------------- exec parameters
modparam("exec", "setvars", 1)
modparam("exec", "time_to_kill", 10)
# ------------- registration parameters
modparam("registrar", "nat_flag", 2)
modparam("registrar", "min_expires", 60)
modparam("registrar", "max_expires", 86400)
modparam("registrar", "default_expires", 3600)
modparam("registrar", "append_branches", 1)
# -- avp params --
modparam("avpops", "avp_url", "mysql://ser:heslo@localhost/ser")
modparam("avpops", "avp_table", "usr_preferences")
#modparam("avpops", "use_domain", "1")
modparam("avpops", "uuid_column", "uuid")
modparam("avpops", "username_column", "username")
modparam("avpops", "domain_column", "domain")
modparam("avpops", "attribute_column", "attribute")
modparam("avpops", "value_column", "value")
modparam("avpops", "type_column", "type")
modparam("avpops", "avp_aliases",
"voicemail=i:500;calltype=i:700;fwd_no_answer_type=i:701;fwd_busy_type=i:702")
# To use more than one tables example
#modparam("avpops", "db_scheme",
"scheme1:table=subscriber;uuid_column=uuid;value_column=first_name")
# -- tm params --
modparam("tm", "fr_timer", 15)
modparam("tm", "fr_inv_timer", 22)
modparam("tm", "wt_timer", 5)
modparam("tm", "fr_inv_timer_avp", "inv_timeout")
# -- pft params --
modparam("pdt", "db_table", "prefix_domain")
modparam("pdt", "prefix", "")
modparam("pdt", "hsize_2pow", 2)
modparam("pdt", "sync_time", 300)
modparam("pdt", "clean_time", 600)
# ------------- logging parameters
modparam("xlog", "buf_size", 8192)
# -- group params --
modparam("group", "table", "grp")
modparam("group", "user_column", "username")
modparam("group", "domain_column", "domain")
modparam("group", "group_column", "grp")
# ------------------------- request routing logic -------------------
# main routing logic
route {
# ------------------------------------------------------------------------
# Sanity Check Section
# ------------------------------------------------------------------------
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483", "Too Many Hops");
break;
};
if (msg:len > max_len) {
sl_send_reply("513", "Message Overflow");
break;
};
# ------------------------------------------------------------------------
# NOTIFY Keep-Alive Section
# ------------------------------------------------------------------------
if ((method=="NOTIFY") && search("^Event: keep-alive")) {
sl_send_reply("200", "OK");
break;
};
# ------------------------------------------------------------------------
# OPTIONS Section
# ------------------------------------------------------------------------
if (method=="OPTIONS") {
options_reply();
break;
};
# ------------------------------------------------------------------------
# NAT Test Section #1
# ------------------------------------------------------------------------
if (method=="REGISTER" && client_nat_test("3")) {
fix_contact();
force_rport();
setflag(2);
};
# ------------------------------------------------------------------------
# Registration Section
# ------------------------------------------------------------------------
if (method=="REGISTER") {
if (!is_from_local()) {
sl_send_reply("403", "Unknown Domain");
break;
};
if (!www_authorize("", "subscriber")) {
www_challenge("", "0");
break;
};
if (!check_to()) {
sl_send_reply("401", "Unauthorized");
break;
};
# To - Use To username and (optionally) domain to check
if (is_user_in("To", "demo-disabled")) {
sl_send_reply("403", "Your evaluation period has expired");
break;
};
# To - Use To username and (optionally) domain to check
if (is_user_in("To", "disabled")) {
sl_send_reply("403", "Your account has been disabled");
break;
};
# snom sip phones use this header to start their
# keep-alive mechanism for NAT bindings
append_to_reply("P-NAT-Refresh: 15\r\n");
if (!save("location")) {
sl_reply_error();
};
break;
};
# ------------------------------------------------------------------------
# Accounting Section # 1
#
# NOTE: We test for flag 14 because we do not want to record Click2Dial
# entries
# ------------------------------------------------------------------------
if ((method=="INVITE" || method=="BYE") && !isflagset(14)) {
setflag(1);
};
# ------------------------------------------------------------------------
# NAT Tear-Down Section
# ------------------------------------------------------------------------
if ((method == "BYE" || method == "CANCEL")) {
end_media_session();
};
# ------------------------------------------------------------------------
# Record Route Section
#
# we record-route all messages -- to make sure that subsequent messages
# will go through our proxy; that's particularly good if upstream and
# downstream entities use different transport protocol
# ------------------------------------------------------------------------
if (!method=="REGISTER") {
record_route();
};
# ------------------------------------------------------------------------
# Loose Route Section
#
# Grant route routing if route headers present
# ------------------------------------------------------------------------
if (loose_route()) {
route(2);
break;
};
# ------------------------------------------------------------------------
# NAT Test Section #1
# ------------------------------------------------------------------------
if (client_nat_test("3") && !search("^Record-Route:")) {
force_rport();
fix_contact();
};
# ------------------------------------------------------------------------
# PSTN Section
# ------------------------------------------------------------------------
if (method=="INVITE") { ## Deny PSTN to 0204 and 095
if ((uri=~"^sip:0204[0-9]*@") || (uri=~"^sip:095[0-9]*@")) {
sl_send_reply("503", "Service Unavailable");
break;
};
};
# ------------------------------------------------------------------------
# Alias Routing Section
# ------------------------------------------------------------------------
lookup("aliases");
if (!uri==myself) {
route(2); # local domain call
break;
};
# ------------------------------------------------------------------------
# Load ACL Section
# ------------------------------------------------------------------------
if (method=="INVITE" && !isflagset(14)) {
log(1, "SER: Load ACL\n");
if (is_from_local() || is_uri_host_local()) {
if (is_user_in("From", "int")) {
log(1, "SER: a INT user\n");
setflag(29);
};
if (is_user_in("From", "free-pstn")) {
log(1, "SER: a FREE-PSTN user\n");
setflag(28);
};
};
if (avp_db_load("$ruri/username", "s:anoncallrej")) {
if (avp_check("s:anoncallrej", "eq/y/i")) {
log(1, "SER: a ANON-CALL-REJ user\n");
setflag(24);
};
};
};
# ------------------------------------------------------------------------
# Anonymous Call Rejection Section # 24
# ------------------------------------------------------------------------
if (isflagset(24) && (method=="INVITE") &&
search("^(f|F)rom:.*(a|A)nonymous")) {
route(8);
break;
};
# ------------------------------------------------------------------------
# Speed Dialing Section
# ------------------------------------------------------------------------
if ((method=="INVITE") && (uri=~"^sip:[0-9]{2}@.*")) {
sd_lookup("speed_dial");
};
# ------------------------------------------------------------------------
# 002 International Call Section # 29
# ------------------------------------------------------------------------
if (method=="INVITE" && uri=~"^sip:002[0-9]*@") {
if (isflagset(29)) {
route(6);
} else {
sl_send_reply("503", "Service Unavailable");
};
break;
};
# ------------------------------------------------------------------------
# 0XXXXXXXXX Domestic Call Section # 29
# ------------------------------------------------------------------------
if (method=="INVITE" && uri=~"^sip:0[0-9]{9}@") {
if (isflagset(29)) {
route(6);
} else {
sl_send_reply("503", "Service Unavailable");
};
break;
};
# ------------------------------------------------------------------------
# URI Compare Section
#
# Here we compare the "from" and "to" to see if the caller is dialing
# their own extension. If so then we route to voicemail(31) if needed
# ------------------------------------------------------------------------
if (method=="INVITE") {
avp_write("$from", "i:34");
if (avp_check("i:34", "eq/$ruri/i")) {
if (isflagset(31)) {
route(5);
break;
} else {
sl_send_reply("486", "Busy");
break;
};
};
};
# ------------------------------------------------------------------------
# Do Not Disturb Section
# ------------------------------------------------------------------------
if (avp_db_load("$ruri/username", "s:donotdisturb")) {
if (avp_check("s:donotdisturb", "eq/y/i")) {
route(5);
break;
};
};
# ------------------------------------------------------------------------
# Blind Call Forwarding Section
# ------------------------------------------------------------------------
if (method=="INVITE") {
# here we must store the current (aka original) R-URI because if
# we set call forwarding and the forwarded number is busy then we
# need to use this original R-URI to determine which voicemail
# box we should go to
if (isflagset(31)) {
avp_write("$ruri", "$voicemail");
};
if (avp_db_load("$ruri/username", "s:callfwd")) {
avp_pushto("$ruri", "s:callfwd");
# lookup the call fowarding number to see if it is a served
# sip number or a PSTN number
# check forwarding number rules
route(1);
if (avp_check("$calltype", "eq/-/i")) {
sl_send_reply("503", "Service Unavailable");
break;
};
# test for domestic PSTN gateway
if (avp_check("$calltype", "eq/dom/i")) {
route(3);
break;
};
# test for international PSTN gateway
if (avp_check("$calltype", "eq/int/i")) {
route(6);
break;
};
};
};
# ------------------------------------------------------------------------
# Call Routing Section
# ------------------------------------------------------------------------
if (!lookup("location")) {
# if flag 31 (ie voicemail) is set and we made it here this means
# the user's phone is not registered anywhere. We'll forward to
# voicemail after this block because we need to check the call
# forward settings first
if (isflagset(31)) {
# flag 19 means the user has voicemail but is not online
# so we need to remember to send to voicemail if call
# forwarding is not enabled
setflag(19);
};
if (method=="INVITE") {
if (does_uri_exist()) {
# subscriber record found, but they're offline
sl_send_reply("480", "Temporarily Unavailable");
break;
};
if (uri=~"^sip:0[0-9]{9}@") {
# Send to PSTN Gateway
if (isflagset(28)) {
route(3);
} else {
sl_send_reply("503", "Service Unavailable");
};
break;
};
sl_send_reply("404", "User Not Found");
break;
};
};
# ------------------------------------------------------------------------
# Call Forwarding Section
# ------------------------------------------------------------------------
if (method=="INVITE") {
# save R-URI in a temp AVP for later use
avp_write("$ruri", "i:99");
# only load the forward no answer option if voice mail is not enabled
if (!isflagset(31)) {
if (avp_db_load("$ruri/username", "s:fwdnoanswer")) {
route(1);
if (!avp_check("$calltype", "eq/-/i")) {
if (avp_check("$calltype", "eq/dom/i")) {
avp_write("dom", "$fwd_no_answer_type");
} else if (avp_check("$calltype", "eq/int/i")) {
avp_write("int", "$fwd_no_answer_type");
} else {
avp_write("sip", "$fwd_no_answer_type");
}
setflag(27);
};
};
};
if (avp_db_load("$ruri/username", "s:fwdbusy")) {
route(1);
if (!avp_check("$calltype", "eq/-/i")) {
if (avp_check("$calltype", "eq/dom/i")) {
avp_write("dom", "$fwd_busy_type");
} else if (avp_check("$calltype", "eq/int/i")) {
avp_write("int", "$fwd_busy_type");
} else {
avp_write("sip", "$fwd_busy_type");
}
setflag(26);
};
};
avp_pushto("$ruri", "i:99");
};
if (isflagset(19)) {
# send to voicemail
route(5);
} else {
route(2);
};
}
route[1] {
# Here we have route checks for all the call forwarding stuff.
# The return values are passed as AVP $calltype as follows:
#
# "-" = R-URI is not allowed
# "dom" = R-RURI is a domestic call
# "int" = R-RURI is an international call
# "sip" = R-RURI is a sip call
avp_write("-", "$calltype");
# Call rejected
if ((uri=~"^sip:0204[0-9]*@") ||
(uri=~"^sip:095[0-9]*@") ||
(uri=~"^sip:[0-9]{3}@")) {
break;
};
lookup("aliases");
if (!lookup("location")) {
if (uri=~"^sip:0[0-9]{9}@") {
# test for domestic PSTN number
if (isflagset(28)) {
avp_write("dom", "$calltype");
};
# } else if (uri=~"^sip:011[0-9]*@") {
} else if (uri=~"^sip:002[0-9]*@") {
# test for international PSTN number
if (isflagset(29)) {
avp_write("int", "$calltype");
};
};
break;
};
avp_write("sip", "$calltype");
}
route[2] {
if ((method=="INVITE") && !allow_trusted()) {
if (!proxy_authorize("", "subscriber")) {
proxy_challenge("", "0");
break;
} else if (!check_from()) {
log(1, "Spoofed SIP call attempt");
sl_send_reply("403", "Use From=ID");
break;
} else if (!(is_from_local() || is_uri_host_local())) {
sl_send_reply("403", "Please register to use our service");
break;
};
};
if (uri=~"[@:](192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)" &&
!search("^Route:")){
sl_send_reply("479", "We don't forward to private IP addresses");
break;
};
if (method=="INVITE" || method=="ACK") {
use_media_proxy();
};
t_on_failure("1");
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
route[3] {
# All Domestic Calls Go To PSTN
if (method=="INVITE") {
if (!proxy_authorize("", "subscriber")) {
proxy_challenge("", "0");
break;
} else if (!check_from()) {
log(1, "Spoofed SIP call attempt");
sl_send_reply("403", "Use From=ID");
break;
} else if (!(is_from_local() || is_uri_host_local())) {
sl_send_reply("403", "Please register to use our service");
break;
};
};
# SIP->PSTN calls get 45 seconds to timeout
avp_write("i:45", "inv_timeout");
rewritehost("xx.xx.xx.xx");
if (uri=~"[@:](192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)" &&
!search("^Route:")){
sl_send_reply("479", "We don't forward to private IP addresses");
break;
};
if (method=="INVITE" || method=="ACK") {
use_media_proxy();
};
if (isflagset(31)) {
t_on_failure("1");
};
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
route[4] {
# voicemail route #1
#
# this path this executed during these conditions:
#
# cond 1) the called number is in the location table
# but the callee did not answer the phone
# (ie, failover to voicemail)
#if (isflagset(25)) {
# replace("^From:(.*)>" , "From: \"Anonymous\"
<sip:someone@anonymous.invalid>");
#};
rewritehostport("99.99.99.100:5060");
append_branch();
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
route[5] {
# voicemail route #2
#
# this path this executed during these conditions:
#
# cond 1) the called number is not in the location table
# cond 2) the from_uri == to_uri (ie, caller==callee)
if (method=="INVITE" || method=="ACK") {
use_media_proxy();
};
rewritehostport("99.99.99.100:5060");
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
route[6] {
# All International Calls Go To PSTN
if (method=="INVITE") {
if (!proxy_authorize("", "subscriber")) {
proxy_challenge("", "0");
break;
} else if (!check_from()) {
log(1, "Spoofed SIP call attempt");
sl_send_reply("403", "Use From=ID");
break;
} else if (!(is_from_local() || is_uri_host_local())) {
sl_send_reply("403", "Please register to use our service");
break;
};
};
# SIP->PSTN calls get 45 seconds to timeout
avp_write("i:45", "inv_timeout");
rewritehost("xx.xx.xx.xx");
if (uri=~"[@:](192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)" &&
!search("^Route:")){
sl_send_reply("479", "We don't forward to private IP addresses");
break;
};
if (method=="INVITE" || method=="ACK") {
use_media_proxy();
};
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
route[7] {
# caller blocked announcment
#
# this path this executed if a caller has been blocked
if (method=="INVITE" || method=="ACK") {
use_media_proxy();
};
rewriteuri("sip:699@99.99.99.100:5060");
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
route[8] {
# anonymous call rejection announcment
#
# this path this executed for anonymous callers
if (method=="INVITE" || method=="ACK") {
use_media_proxy();
};
rewriteuri("sip:698@99.99.99.100:5060");
t_on_reply("1");
if (!t_relay()) {
if (method=="INVITE" || method=="ACK") {
end_media_session();
};
sl_reply_error();
};
}
onreply_route[1] {
# Not all 2xx messages have a content body so here we
# make sure our Content-Length > 0 to avoid a parse error
if (status=~"(180)|(183)|2[0-9][0-9]") {
if (!search("^Content-Length:\ 0")) {
use_media_proxy();
};
};
if (client_nat_test("1")) {
fix_contact();
};
}
failure_route[1] {
# if caller hung up then don't sent to voicemail
if (t_check_status("487")) {
break;
};
if (isflagset(26) && t_check_status("486")) {
# forward busy is flag 26
if (avp_pushto("$ruri", "s:fwdbusy")) {
avp_delete("s:fwdbusy");
append_branch();
resetflag(26);
# test for domestic PSTN gateway
if (avp_check("$fwd_busy_type", "eq/dom/i")) {
# test for domestic PSTN gateway
route(3);
} else if (avp_check("$fwd_busy_type", "eq/int/i")) {
# test for international PSTN gateway
route(6);
} else {
# default to sip call
route(2);
};
break;
};
};
# here we can have either voicemail __OR__ forward no answer
if (isflagset(27) && t_check_status("408")) {
# forward no answer is flag 27
if (avp_pushto("$ruri", "s:fwdnoanswer")) {
avp_delete("s:fwdnoanswer");
append_branch();
resetflag(27);
if (avp_check("$fwd_no_answer_type", "eq/dom/i")) {
# test for domestic PSTN gateway
route(3);
} else if (avp_check("$fwd_no_answer_type", "eq/int/i")) {
# test for international PSTN gateway
route(6);
} else {
# default to sip call
route(2);
};
break;
};
} else if (isflagset(31) && avp_pushto("$ruri", "$voicemail")) {
avp_delete("$voicemail");
route(4);
break;
};
}