# =============================== # This is an auto-generated file. # Please do not edit. # =============================== # Copyright (C) 2006, 2007 Greger Viken Teigre # This configuration file was generated by the config autobuild system found as a # part of ser, a free SIP server. # ser is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version # # ser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # ------------------------------------- # # Debug level on logging debug=3 # memory debug log level memdbg=10 # memory statistics log level memlog=10 # Fork and create children (no=run single process for debugging purposes) fork=yes # Log to stderr (only use this of fork=no) log_stderror=no # Log to the defined syslog facility log_facility=LOG_LOCAL0 # IP address to listen to listen=192.168.50.87 # Port to listen on port=5060 # Aliases used by uri!=myself checks to identity locally destined messages alias=mydomain.com # Number of children to fork per port per protocol children=4 # Is this host multihomed? mhomed=no # Should dns resolving be used? dns=no # Should reverse dns resolving be used? rev_dns=no # Should reverse dns resolving be used? disable_core_dump=yes # *************Your local directives ***************** # *** Common # *** Specific # Load the stateless transaction module (sl_reply etc) loadmodule "/home/linus/gao/usr/local/lib/ser/modules/sl.so" # Load the transaction stateful module (t_relay() etc) loadmodule "/home/linus/gao/usr/local/lib/ser/modules/tm.so" # Load the record routing module. Needed for making sure messages go through our server loadmodule "/home/linus/gao/usr/local/lib/ser/modules/rr.so" # Load maxfwd for stopping loops loadmodule "/home/linus/gao/usr/local/lib/ser/modules/maxfwd.so" # Load the user location module to store and retrieve user locations loadmodule "/home/linus/gao/usr/local/lib/ser/modules/usrloc.so" # Load the registrar module to handle registrations loadmodule "/home/linus/gao/usr/local/lib/ser/modules/registrar.so" # Load the xlog module for advanced logging with parameters loadmodule "/home/linus/gao/usr/local/lib/ser/modules/xlog.so" # Load the ctl module for the control socket interface. loadmodule "/home/linus/gao/usr/local/lib/ser/modules/ctl.so" # Load the gflags, global flags module. loadmodule "/home/linus/gao/usr/local/lib/ser/modules/gflags.so" # Load textops used for searching/selecting text in messages and manipulating headers. loadmodule "/home/linus/gao/usr/local/lib/ser/modules/textops.so" # Load the sanity check module to do integrity checks on incoming messages. loadmodule "/home/linus/gao/usr/local/lib/ser/modules/sanity.so" # Load the mysql connector module. loadmodule "/home/linus/gao/usr/local/lib/ser/modules/mysql.so" # Load the auth module with all the core authentication functions. loadmodule "/home/linus/gao/usr/local/lib/ser/modules/auth.so" # Load the auth module with the database functions. loadmodule "/home/linus/gao/usr/local/lib/ser/modules/auth_db.so" # The uri_db module uses database to check the uri. loadmodule "/home/linus/gao/usr/local/lib/ser/modules/uri_db.so" # The avp_db module allows loading of user attributes from database. loadmodule "/home/linus/gao/usr/local/lib/ser/modules/avp_db.so" # Load domain module used to verify the local domains. loadmodule "/home/linus/gao/usr/local/lib/ser/modules/domain.so" # The acc_db module allows accounting directly to database. loadmodule "/home/linus/gao/usr/local/lib/ser/modules/acc_db.so" # Load the nathelper module, which regularly pings UAs behind NAT and connects to rtpproxy (iptel.org). loadmodule "/home/linus/gao/usr/local/lib/ser/modules/nathelper.so" # avp module has a long range of functions for attribute manipulation. loadmodule "/home/linus/gao/usr/local/lib/ser/modules/avp.so" # *** Your loaded modules # Flags set be various modules # The flag set when the script has passed through the failure route flags FLAG_FAILUREROUTE: 2; # The FLAG_ACC flag is set to mark a message for logging to the database or syslog flags FLAG_ACC: 1; flags FLAG_NAT_UAC: 6, FLAG_NAT_UAS: 7; # We set database mode to 0 = do not save to database backend (keep in memory), 1 = write-through to database modparam("usrloc", "db_mode", 1) # ctl module params # by default ctl listens on unixs:/tmp/ser_ctl if no other address is # specified in modparams; this is also the default for sercmd modparam("ctl", "binrpc", "unixs:/tmp/ser_ctl") # listen on the "standard" fifo for backward compatibility modparam("ctl", "fifo", "fifo:/tmp/ser_fifo") # We turn on full lr (adds lr=on as uri parameter, not lr). # This should have higher compatibility with some user agents. modparam("rr", "enable_full_lr", 1) # Encrypt dialog cookies with this secret modparam("rr", "cookie_secret", "ChangeThisIfYouStoreSecretStuffInCookie") # Causes global flags and domain attributes to be loaded from database on SER start-up. modparam("gflags", "load_global_attrs", 1) modparam("domain", "load_domain_attrs", 1) # Set the name of the flag we are going to set when we want to account a message. modparam("acc_db", "log_flag", "FLAG_ACC") # Set the name of the flag we are going to set when we want to account a missed message. modparam("acc_db", "log_missed_flag", "FLAG_ACC_MISSED") # Set the name of the flag which will be saved when contact details are stored when a user agent registers. modparam("registrar", "save_nat_flag", "FLAG_NAT_UAC") # Set the name of the flag that should be set when NAT info is loaded from the user location. modparam("registrar", "load_nat_flag", "FLAG_NAT_UAS") # Set the number of seconds between each keepalive sent to each user agent behind NAT modparam("nathelper", "natping_interval", 30) # Which method to use when sending a keepalive. OPTIONS will generate a 200 OK from the user agent. modparam("nathelper", "natping_method", "OPTIONS") # Only send keepalives to contacts in user location that is registered as behind NAT? modparam("nathelper", "ping_nated_only", 1) # The socket where rtpproxy listens. modparam("nathelper", "rtpproxy_sock", "udp:127.0.0.1:22222") # The authentication related modules and which database to use. modparam("auth_db|usrloc|uri_db", "db_url", "mysql://ser:heslo@localhost/ser") # The modules loading values on SER start-up and the database to use. modparam("domain|gflags", "db_url", "mysql://ser:heslo@localhost/ser") # Accounting to database and the database to use. modparam("acc_db", "db_url", "mysql://ser:heslo@localhost/ser") # We can store some of our important attributes (inside the messages) avpflags dialog_cookie; # ************* Your local module parameters ***************** # *** Common # *** Specific # Main route, executed for all messages route { # ------------------------------------------------------------------------ # Sanity Check Section # ------------------------------------------------------------------------ sanity_check(); # Check whether we might be in a loop. if (!mf_process_maxfwd_header("10")) { sl_reply("483", "Too Many Hops"); exit; } if (msg:len > max_len) { sl_reply("513", "Message Overflow"); exit; } # Log all incoming messages to see start of processing if(is_gflag("29")){ xlog("L_NOTICE","INCOMING - %rm\nFrom: %is(%fu)\nTo: %ru\nCall-ID: %ci\n"); } # We only set the flag for initial INVITEs (i.e. without the to tag) # We then set a record-route cookie in the INVITE to make sure that all messages are accounted. if (method=="INVITE" && @to.tag=="") { setflag(FLAG_ACC); } # ------------------------------------------------------------------------ # Handling messages with Route headers (aka loose routing) # ------------------------------------------------------------------------ if (loose_route()) { if(is_gflag("31")){ xlog("L_NOTICE"," loose routed - %rm\nFrom: %is(%fu)\nTo: %ru\nCall-ID: %ci\n"); } # After loose_route(), any attributes found in the dialog cookie have been set. # Check if this dialog is accounted. if ($accounting) { setflag(FLAG_ACC); } route(RELAY); exit; } # ------------------------------------------------------------------------ # Record Route Section # ------------------------------------------------------------------------ else if (method!="REGISTER") { # If the accounting flag is set, we want to store that info in a dialog cookie # This way we can quickly check if we should account. if (isflagset(FLAG_ACC)) { $accounting = true; setavpflag($accounting, "dialog_cookie"); } record_route(); }; # If the ACK has more hops before reaching the user agent, it will have a Route header # and be forwarded above. If next hop is a user agent, the Request URI will be the ip:port # found in Contact of the original OK from the user agent, but will not be loose routed. # Just relay the ACK to the user agent. if (method=="ACK") { if(is_gflag("31")){ xlog("L_NOTICE"," ACK relayed using ruri - %rm\nFrom: %is(%fu)\nTo: %ru\nCall-ID: %ci\n"); } route(RELAY); exit; } # check if the caller is from a local domain (f=from, d=domain, $f will be set) lookup_domain("$fd", "@from.uri.host"); # check if the callee is at a local domain (t=to, d=domain, $t will be set) # If we have no To tag (dialog creating messages), we use request uri, but # but if this is an in-dialog message (like BYE with last hop before UA here) # we use the To header. if(@to.tag=="") { lookup_domain("$td", "@ruri.host"); } else { lookup_domain("$td", "@to.uri.host"); } # we dont know the domain of the caller and also not # the domain of the callee -> someone uses our proxy as # a relay if (!$t.did && !$f.did) { sl_reply("403", "Relaying Forbidden"); exit; } # Do NAT detection route(NAT_DETECT); # ------------------------------------------------------------------------ # Message Type Processing Section # NOTE!!! It is assumed that all messages reaching this point are destined # for the local server (REGISTER) or for UAs registered locally. (see nonlocal.m4) # ------------------------------------------------------------------------ if (method=="REGISTER") { route(REGISTER); exit; } # Authenticate route(AUTHENTICATE); # All local, non-ACKs, non-REGISTER are assumed to be part of a potential # new dialog (standalone MESSAGE and NOTIFYs without dialog-creation will ex. also reach here) route(NEWDIALOG); # By now, the request uri should be correct, relay if(is_gflag("29")){ xlog("L_NOTICE","No route matched for the request\nCall-Id: %ci\n"); }; sl_reply("404", "No route matched"); } # end main route route[RELAY] { # Log all outgoing messages if(is_gflag("29")){ xlog("L_NOTICE","OUTGOING - %rm\nFrom: %is(%fu)\nTo: %ru\nCall-ID: %ci\n"); } # Send to NAT fixing route(NAT_MANGLE); # And make sure that the replies goes through the reply route for NAT fixing t_on_reply("NAT_MANGLE"); # If we have been in the failure route, this is a forwarding after a non-answered attempt. # We need to add a branch. if (isflagset(FLAG_FAILUREROUTE)) { append_branch(); } # We want all failure responses to go through our failure route. t_on_failure("FAILURE_ROUTE"); # ------------------------------------------------------------------------ # Default Message Handler # ------------------------------------------------------------------------ # t_relay will act based on the current request URI, as well as any # overruling received parameters (i.e. for NATed user agents) # UDP to TCP and vice versa works as well. if (!t_relay()) { sl_reply_error(); }; exit; } route[REGISTER] { # ------------------------------------------------------------------------ # REGISTER Message Handler # ------------------------------------------------------------------------ # From lookup_domain, $t.did should be set if we found the domain as ours. if (!$t.did) { if(is_gflag("29")){ xlog("L_NOTICE","%rm From <%fu> Attempted REGISTER from non-local domain\nCall-ID: %ci\n"); }; sl_reply("403", "Attempting to register with unknown domain"); exit; } # We check that Authorization header in the message contains valid credentials found in the # table with the same name. if (!www_authenticate("$fd.digest_realm", "credentials")) { # $? represents the return error code from www_authenticate() if ($? == -2) { if(is_gflag("31")){ xlog("L_NOTICE"," REGISTER - %rm From <%fu> 500 Internal Server Error\nCall-ID: %ci\n"); }; sl_reply("500", "Internal Server Error"); } else if ($? == -3) { if(is_gflag("31")){ xlog("L_NOTICE"," REGISTER - %rm From <%fu> 400 Bad Request\n"); }; sl_reply("400", "Bad Request"); } else { # After www_authenticate(), $digest_challenge should be set if no credentials were found. # We append the challenge to reply and send 401 Unauthorized. if ($digest_challenge) { append_to_reply("%$digest_challenge"); } sl_reply("401", "Unauthorized"); } # We didn't have a valid set of credentials, so we exit. exit; } # www_authenticate set $uid, so let's store it. $authuid=$uid; # Check if the authenticated user is the same as the target user. # We use the uri in the To field to lookup the user's uid. If none is found, the To user is unknown. if (!lookup_user("$tu.uid", "@to.uri")) { sl_reply("404", "Trying to register unknon user (To)"); exit; } # $f.uid set by www_authenticate() should match the uid we should looked up if ($authuid != $tu.uid) { sl_reply("403", "Authentication and To-Header mismatch"); exit; } # We use the uri in From to look up the uid. if (!lookup_user("$fu.uid", "@from.uri")) { sl_reply("404", "Expect a known user in From"); exit; } # The looked up $fu.uid is checked against the Authentication user if ($authuid != $fu.uid) { sl_reply("403", "Authentication and From-Header mismatch"); exit; } if (!save_contacts("location")) { sl_reply("400", "Invalid REGISTER Request"); exit; }; exit; } # End route[REGISTER] route[AUTHENTICATE] { # RFC3261 says you are not allowed to challenge these methods if (method=="CANCEL" || method=="ACK") { return; } # If the domain in From is unknown, this is an incoming call from the Internet, let it pass. if (! $f.did) { return; } # We check that Authorization header in the message contains valid credentials found in the # table with the same name. if (!proxy_authenticate("$fd.digest_realm", "credentials")) { # $? represents the return error code from proxy_authenticate() if ($? == -2) { if(is_gflag("31")){ xlog("L_NOTICE"," AUTHENTICATE - %rm From <%fu> 500 Internal Server Error\nCall-ID: %ci\n"); }; sl_reply("500", "Internal Server Error"); } else if ($? == -3) { if(is_gflag("31")){ xlog("L_NOTICE"," AUTHENTICATE - %rm From <%fu> 400 Bad Request\n"); }; sl_reply("400", "Bad Request"); } else { # After www_authenticate(), $digest_challenge should be set if no credentials were found. # We append the challenge to reply and send 407 Proxy Authentication Required. if ($digest_challenge) { append_to_reply("%$digest_challenge"); } sl_reply("407", "Proxy Authentication Required"); } # We didn't have a valid set of credentials, so we exit. exit; } # proxy_authenticate set $uid, so let's store it. $authuid=$uid; # Use the uri in the From header and look up the uid. If not found, delete the uri attribute. if (!lookup_user("$fu.uid", "@from.uri")) { del_attr("$uid"); } # Check the found uid against the authenticated uid. if ($fu.uid != $authuid) { sl_reply("403", "Fake Identity"); exit; } # load the user attributes (preferences) of the caller. $fu.yourattr should now be set if set in the # user preferences table. load_attrs("$fu", "$f.uid"); } route[NEWDIALOG] { # If we found the domain of the From user, but not the To user, this is an outgoing Internet call. if ($f.did && ! $t.did) { route(RELAY); exit; } # If we don't know the user, it is not for a local user. if (!lookup_user("$tu.uid", "@ruri")) { # If we have a PSTN gateway, the call is from a local domain and the dial plan matches... if ($f.did && $gw_ip && uri=~"sips?:\+?[0-9]{3,18}@.*") { # If the user's $asserted_id is set, add a Remote-Party-ID header if ($asserted_id) { # Compose the header xlset_attr("$rpidheader", ";screen=yes"); # Add the header field, replace if it already exists replace_attr_hf("Remote-Party-ID", "$rpidheader"); } #Convert the $gw_ip into a domain part of a uri and set request uri, then relay to gateway. attr2uri("$gw_ip", "domain"); route(RELAY); exit; } # User is not known and request uri does not match PSTN dialplan. return; } # Use the looked up uid and load the user attributes. load_attrs("$tu", "$t.uid"); # The attribute fwd_always_target contains sip forwarding info. # If it happens to be our SIP, it will be sent in loop back for new processing. if ($tu.fwd_always_target) { attr2uri("$tu.fwd_always_target"); route(RELAY); exit; } if (!lookup_contacts("location")) { if(is_gflag("30")){ xlog("L_NOTICE"," NEWDIALOG - 480 User Offline\nCall-Id: %ci\n"); }; sl_reply("480", "User Offline"); exit; } # We have also loaded the NAT_UAS flag, now set the attribute we use throughout the config. if (isflagset("FLAG_NAT_UAS")) { if(is_gflag("30")){ xlog("L_NOTICE"," NEWDIALOG - callee is behind NAT\nCall-Id:%ci\n"); }; $nated_callee = true; } # If the fr_inv_timer attribute (in ms) was set for callee (i.e. loaded from database), # we want to set the total time before we time out an INVITE answered with a 1xx reply # This is the ringing time, the default is 120,000 ms if ($t.fr_inv_timer) { # If also the callee has set fr_timer, we also want to set the time-out (in ms) # we want to wait if the user agent has not answered at all with 1xx (maybe it is offline) # Default is 30,000ms if ($t.fr_timer) { t_set_fr("$t.fr_inv_timer", "$t.fr_timer"); # We only have the INVITE timer } else { t_set_fr("$t.fr_inv_timer"); } } # Relay it to the location(s) of the found user route(RELAY); exit; } # End route[NEWDIALOG] route[NAT_DETECT] { # Skip requests from ourselves if (src_ip == 127.0.0.1) return; # Skip requests that already passed a proxy if (is_present_hf("^Record-Route:")) { return; } # This function checks various parts of the message for privat IP addresses. if (nat_uac_test("19")) { # Explicitly set the rport parameter with the source port of the message force_rport(); # Set the flag we set tp store that the caller (UAC) is behind a NAT setflag("FLAG_NAT_UAC"); # Set the attribute we use in the config to identify that the caller is behind a NAT $nated_caller = true; } } # End NAT_DETECT route[NAT_MANGLE] { # If none of the parties are NATed, just return if (!$nated_caller && !$nated_callee) { return; } # We are not allowed to touch the Contact of a REGISTER, but this will cause save_contact() # to save the correct location. if (method == "REGISTER") { if(is_gflag("31")){ xlog("L_NOTICE"," NAT_MANGLE: Fixing REGISTER for NATed client\nCall-ID: %ci\n"); }; fix_nated_register(); } # For all other message, we need to change the Contact header so that callee gets the correct public info. else { if(is_gflag("31")){ xlog("L_NOTICE"," NAT_MANGLE: Fixing NATed %rm\nCall-ID: %ci\n"); }; fix_nated_contact(); } # For BYE and CANCELs, we want to end the proxying. if (method == "BYE" || method == "CANCEL") { if(is_gflag("31")){ xlog("L_NOTICE"," NAT_MANGLE: Ending proxy session %rm\nCall-ID: %ci\n"); }; } # If we are not routing this message based on Route headers, add a dialog cookie, so we store # NAT info into the dialog (for use in subsequent messages). if (!$loose_route) { setavpflag("$nated_caller", "dialog_cookie"); setavpflag("$nated_callee", "dialog_cookie"); } # For all INVITE messages that are NATed, we want to force RTP through our RTP proxy. if (method == "INVITE") { if(is_gflag("31")){ xlog("L_NOTICE"," NAT_MANGLE: Starting proxy session %rm\nCall-ID: %ci\n"); }; } } # ************* Your local routes ***************** # *** Common # *** Specific onreply_route[NAT_MANGLE] { if(is_gflag("29")){ xlog("L_NOTICE","INCOMING REPLY - %is(%fu): %rs(%tu)\nCall-Id:%ci\n"); }; # Just return if callee is not NATed. if (!$nated_callee) return; # Fix the Contact header fix_nated_contact(); # Only replies to INVITEs carry media if (@cseq.method != "INVITE") return; # Early media and 2xx codes with sdp content should be proxied if ((status =~ "(180)|(183)|2[0-9][0-9]") && search("^(Content-Type|c):.*application/sdp")) { if(is_gflag("30")){ xlog("L_NOTICE"," onreply_route[NAT_MANGLE] - forcing rtp proxy\nCall-Id: %ci\n"); }; # Force media through our RTP proxy force_rtp_proxy(); } } # end onreply_route[NAT_MANGLE] failure_route[FAILURE_ROUTE] { # We set the FLAG_FAILUREROUTE, so that we know in other routes that we have been through a failure. setflag(FLAG_FAILUREROUTE); # If we receive Busy here or Busy everywhere, we want to forward. if (t_check_status("486|600")) { # The loaded user attributes from when the INVITE was processed, are still set. # We load the fwd_busy_target attribute (should be SIP uri) and relay. if ($tu.fwd_busy_target) { attr2uri("$tu.fwd_busy_target"); route(RELAY); exit; } } # No answer was received, we may have another forwarding. else if (t_check_status("408|480")) { # Use the user's fwd_noanswer_target if ($tu.fwd_noanswer_target) { attr2uri("$tu.fwd_noanswer_target"); route(RELAY); exit; } } } # End failure_route[FAILURE_ROUTE]