################################### ####### M2 Kamailio proxy/LNP ##### ################################### ####### Global Parameters ######### debug = 2 log_stderror = no log_facility = LOG_LOCAL0 fork = yes children = 4 port = 5060 listen = udp:192.168.1.126:5060 disable_tcp = yes dns = no rev_dns = no mpath = "/usr/local/lib64/kamailio/modules/" server_header = "Server: M2 Proxy server" user_agent_header = "User-Agent: M2 Proxy server" ####### Modules Section ######## loadmodule "tm" loadmodule "kex" loadmodule "sl" loadmodule "rr" loadmodule "pv" loadmodule "maxfwd" loadmodule "textops" loadmodule "siputils" loadmodule "xlog" loadmodule "sanity" loadmodule "nat_traversal" loadmodule "dispatcher" loadmodule "ctl" loadmodule "jsonrpcs" loadmodule "db_mysql" loadmodule "usrloc" loadmodule "registrar" loadmodule "auth" loadmodule "auth_db" loadmodule "nathelper" loadmodule "m2_mnp" # ----------------- setting module-specific parameters --------------- # ----- ctl ----------- modparam("ctl", "binrpc", "/var/run/kamailio/kamailio_ctl") # ----- tm params ----- modparam("tm", "fr_timer", 3000) modparam("tm", "fr_inv_timer", 40000) modparam("tm", "auto_inv_100_reason", "Trying") # ----- rr params ----- # add value to ;lr param to cope with most of the UAs modparam("rr", "enable_full_lr", 1) # do not append from tag to the RR (no need for this script) modparam("rr", "append_fromtag", 0) # ----- dispatcher params ----- modparam("dispatcher", "list_file", "/usr/src/m2/kamailio/dispatcher.list") modparam("dispatcher", "xavp_dst", "_dsdst_") modparam("dispatcher", "xavp_dst_mode", 1) modparam("dispatcher", "xavp_ctx", "_dsctx_") modparam("dispatcher", "xavp_ctx_mode", 1) modparam("dispatcher", "ds_ping_method", "OPTIONS") modparam("dispatcher", "ds_ping_interval", 30) modparam("dispatcher", "ds_probing_mode", 1) modparam("dispatcher", "ds_inactive_threshold", 1) modparam("dispatcher", "ds_probing_threshold", 1) modparam("dispatcher", "ds_hash_size", 12) modparam("dispatcher", "ds_ping_reply_codes", "code=404") # ----- nathelper ----- modparam("nathelper", "natping_interval", 10) modparam("nathelper", "received_avp", "$avp(received_avp)") # ----- registrar ----- modparam("registrar", "default_expires", 1800) modparam("registrar", "min_expires", 60) modparam("registrar", "max_expires", 180) modparam("registrar", "received_avp", "$avp(received_avp)") # ----- usrloc ----- modparam("usrloc", "version_table", 0) modparam("usrloc", "db_mode", 3) modparam("usrloc", "db_url", "mysql://kamailio:kamailio@localhost/mor") # ----- auth db ----- modparam("auth_db", "version_table", 0) modparam("auth_db", "calculate_ha1", yes) modparam("auth_db", "user_column", "op_username") modparam("auth_db", "password_column", "op_password") modparam("auth_db", "db_url", "mysql://kamailio:kamailio@localhost/mor") # ------- m2_mnp ---- # modparam("m2_mnp", "dbhost", "localhost") # modparam("m2_mnp", "dbname", "mor") # modparam("m2_mnp", "dbuser", "root") # modparam("m2_mnp", "dbport", 3306) ####### Routing Logic ######## # main request routing logic route { # per request initial checks route(REQINIT); # handle OPTIONS if (is_method("OPTIONS")) { sl_send_reply("200", "OK"); exit; } # check NAT if (client_nat_test("3")) { fix_contact(); } # handle not implemented request if (!ds_is_from_list() && is_method("SUBSCRIBE")) { xlog("L_NOTICE", "Rejecting $rm from $si:$sp\n"); sl_send_reply("501", "Not Implemented"); exit; } # handle requests within SIP dialogs route(WITHINDLG); ### only initial requests (no To tag) # CANCEL processing if (is_method("CANCEL")) { if (t_check_trans()) { t_relay(); } exit; } t_check_trans(); # record routing for dialog forming requests (in case they are routed) if (is_method("INVITE")) { record_route(); m2_mnp(); if ($avp(m2_mnp:cache_status) == "1") { xlog("L_NOTICE", "NOT Found in cache"); route(SEND_TO_LNP_SERVER); } else { xlog("L_NOTICE", "Found in cache"); route(DISPATCH_AND_RELAY); } } if (is_method("REGISTER")) { route(REGISTER); } route(RELAY); } route[SEND_TO_LNP_SERVER] { ## Send request to LNP server xlog("L_NOTICE", "SEND_TO_LNP_SERVER"); seturi("sip:test@192.168.1.111"); # LNP SERVER IP CHANGE ME t_on_failure("RESPONSE_FROM_LNP"); t_relay(); exit; } failure_route[RESPONSE_FROM_LNP] { ## Send to M2 xlog("L_NOTICE", "RESPONSE_FROM_LNP: FAILURE RESPONSE FROM LNP SERVER. code[$rr $rs]"); if (t_check_status("302")) { xlog("L_NOTICE", "RESPONSE_FROM_LNP: get contacts."); m2_mnp_contacts(); } route(DISPATCH_AND_RELAY); } route[DISPATCH_AND_RELAY] { t_check_trans(); xlog("L_NOTICE", "DISPATCH_AND_RELAY."); revert_uri(); # dispatch destinations if (!ds_is_from_list()) { route(DISPATCH); } route(RELAY); } route[RELAY] { if (!t_relay()) { sl_reply_error(); } exit; } # Per SIP request initial checks route[REQINIT] { if (!mf_process_maxfwd_header("10")) { sl_send_reply("483", "Too Many Hops"); exit; } if(!sanity_check("1511", "7")) { xlog("Malformed SIP message from $si:$sp\n"); exit; } } # Handle requests within SIP dialogs route[WITHINDLG] { if (has_totag()) { # sequential request withing a dialog should # take the path determined by record-routing if (loose_route()) { route(RELAY); } else { if (is_method("ACK")) { if (t_check_trans()) { # non loose-route, but stateful ACK; # must be ACK after a 487 or e.g. 404 from upstream server t_relay(); exit; } else { # ACK without matching transaction ... ignore and discard. exit; } } sl_send_reply("404", "Not here"); } exit; } } # Dispatch requests route[DISPATCH] { # round-robin dispatching on gateways group '1' if (!ds_select_dst("1", "4")) { send_reply("404", "No destination"); exit; } # remove special M2 proxy headers # only M2 proxy is allowed to set these headers remove_hf("x-M2-Originator-ip"); remove_hf("x-M2-Originator-port"); # set specials M2 proxy headers append_hf("x-M2-Originator-ip: $si\r\n"); append_hf("x-M2-Originator-port: $sp\r\n"); xlog("L_NOTICE", "$rm from $si:$sp going to <$ru> dispatched to <$du> server\n"); return; } # Handle registrations route[REGISTER] { if (nat_uac_test("23")) { fix_nated_register(); } if ($expires(max) == 0) { xlog("L_NOTICE", "Unregistration attempt from $ct\n"); } else { xlog("L_NOTICE", "Registration attempt from $ct\n"); } $var(auth_result) = www_authorize("$td", "devices"); if ($var(auth_result) < 0) { switch($var(auth_result)) { case -1: xlog("L_NOTICE", "Generic authentication error (Bad credentials, couldn't parse credentials, no memory left, couldn't fetch from table, ...)\n"); break; case -2: xlog("L_NOTICE", "Registration error - wrong password for user '$au'\n"); break; case -3: xlog("L_NOTICE", "Registration error - authentication user '$au' does not exist\n"); break; case -4: xlog("L_NOTICE", "Registration error - the nonce has expired for user '$au'\n"); break; case -5: xlog("L_NOTICE", "Challenging registration attempt from $ct (asking for credentials)\n"); break; case -6: xlog("L_NOTICE", "Registration error - the nonce has already been used to authenticate a previous request for user '$au'\n"); break; case -8: xlog("L_NOTICE", "Registration error - authuser mismatch for '$au' (From/To/RURI user does not match the authentication user)\n"); break; default: xlog("L_NOTICE", "Unknown registration error\n"); } www_challenge("$td", "1"); exit; }; if (!save("location")) { xlog("L_NOTICE", "Cannot save registration information for user '$au'\n"); sl_reply_error(); } if ($expires(max) == 0) { xlog("L_NOTICE", "User '$au' is successfully unregistered\n"); } else { xlog("L_NOTICE", "User '$au' is successfully registered\n"); } exit; }