123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- ## Kamailio - equivalent of routing blocks in Ruby
- ##
- ## KSR - the new dynamic object exporting Kamailio functions
- ## Relevant remarks:
- ## KSR.x.exit() is not exported in ruby as per KEMI docs, so we use native exit
- ## Module names are capitalised and referenced with double colons - e.g. it's KSR::HDR.append instead of KSR.hdr.append in other KEMI languages
- ## Global variables corresponding to defined values (e.g., flags) in kamailio.cfg
- $FLT_ACC = 1
- $FLT_ACCMISSED = 2
- $FLT_ACCFAILED = 3
- $FLT_NATS = 5
- $FLB_NATB = 6
- $FLB_NATSIPPING = 7
- def ksr_request_route()
- # Per request initial checks
- ksr_route_reqinit()
- ksr_route_natdetect()
- if KSR.is_CANCEL() then
- if KSR::TM.t_check_trans() > 0 then
- ksr_route_relay()
- end
- return
- end
- # Retransmissions
- if !KSR.is_ACK() then
- if KSR::TMX.t_precheck_trans() > 0 then
- KSR::TM.t_check_trans()
- return
- end
- return if KSR::TM.t_check_trans() == 0
- end
- # Handle requests within SIP dialogs
- ksr_route_withindlg()
- # -- only initial requests (no To tag)
- # Authentication
- ksr_route_auth()
- # Record routing for dialog forming requests (in case they are routed)
- KSR::HDR.remove("Route")
- if KSR.is_method_in("IS") then
- KSR::RR.record_route()
- end
- KSR.setflag($FLT_ACC) if KSR.is_INVITE()
- # Dispatch to external
- ksr_route_sipout()
- # Registrations
- ksr_route_registrar()
- if KSR::COREX.has_ruri_user() < 0 then
- # request with no Username in RURI
- KSR::SL.sl_send_reply(484, "Address Incomplete");
- return;
- end
- # User location service
- ksr_route_location()
- return
- end
- def ksr_route_relay()
- if KSR.is_method_in("IBSU") then
- if KSR::TM.t_is_set("branch_route") < 0 then
- KSR::TM.t_on_branch("ksr_branch_manage")
- end
- end
- if KSR.is_method_in("ISU") then
- if KSR::TM.t_is_set("onreply_route") < 0 then
- KSR::TM.t_on_reply("ksr_onreply_manage")
- end
- end
- if KSR.is_INVITE() then
- if KSR::TM.t_is_set("failure_route") < 0 then
- KSR::TM.t_on_failure("ksr_failure_manage")
- end
- end
- if KSR::TM.t_relay() < 0 then
- KSR::SL.sl_reply_error()
- end
- exit
- end
- def ksr_route_reqinit()
- # no connect for sending replies
- KSR.set_reply_no_connect();
- # enforce symmetric signaling
- # send back replies to the source address of request
- KSR.force_rport();
- if !KSR.is_myself_srcip() then
- srcip = KSR::KX.get_srcip();
- if KSR::HTABLE.sht_match_name("ipban", "eq", srcip) > 0 then
- # ip is already blocked
- KSR.dbg("request from blocked IP - " + KSR::KX.get_method() +
- " from " + KSR::KX.get_furi() + " (IP:" +
- srcip + ":" + KSR::KX.get_srcport() + ")\n");
- exit;
- end
- if KSR::PIKE.pike_check_req() < 0 then
- KSR.err("ALERT: pike blocking " + KSR.kx.get_method() +
- " from " + KSR::KX.get_furi() + " (IP:" +
- srcip + ":" + KSR.kx.get_srcport() + ")\n");
- KSR::HTABLE.sht_seti("ipban", srcip, 1);
- exit;
- end
- end
- if KSR::COREX.has_user_agent() > 0 then
- ua = KSR::PV.gete("$ua");
- if ua.include? 'friendly' or ua.include? 'scanner' or
- ua.include? 'sipcli' or ua.include? 'sipvicious' or
- ua.include? 'VaxSIPUserAgent' or ua.include? 'pplsip' then
- KSR::SL.sl_send_reply(200, "OK");
- exit
- end
- end
- if KSR::MAXFWD.process_maxfwd(10) < 0 then
- KSR::SL.sl_send_reply(483, "Too Many Hops");
- exit
- end
- if KSR.is_OPTIONS() and KSR.is_myself_ruri() and KSR::COREX.has_ruri_user() < 0 then
- KSR::SL.sl_send_reply(200, "Keepalive");
- exit
- end
- if KSR::SANITY.sanity_check(17895, 7) < 0 then
- KSR.err("Malformed SIP message from #{KSR::PV.get('$si')}:#{KSR::PV.get('$sp')}\n");
- exit
- end
- end
- def ksr_route_withindlg()
- return if KSR::SIPUTILS.has_totag() < 0
- if KSR::RR.loose_route() > 0 then
- ksr_route_dlguri()
- if KSR.is_BYE() then
- KSR.setflag($FLT_ACC)
- KSR.setflag($FLT_ACCFAILED)
- elsif KSR.is_ACK() then
- ksr_route_natmanage()
- elsif KSR.is_NOTIFY() then
- KSR::RR.record_route()
- end
- ksr_route_relay()
- exit
- end
- if KSR.is_ACK() then
- if KSR::TM.t_check_trans() > 0 then
- ksr_route_relay()
- exit
- else
- exit
- end
- end
- #KSR.info("404ing within dialog")
- KSR::SL.sl_send_reply(404, "Not here");
- exit
- end
- # IP authorization and user authentication
- def ksr_route_auth()
- if !KSR.is_REGISTER() then
- # source IP allowed
- return if KSR::PERMISSIONS.allow_source_address(1).to_i > 0
- end
- if KSR.is_REGISTER() or KSR.is_myself_furi() then
- # auth requests
- if KSR::AUTH_DB.auth_check(KSR::PV.get("$fd"), "subscriber", 1).to_i < 0 then
- KSR::AUTH.auth_challenge(KSR::PV.get("$fd"), 0)
- exit
- end
- # user authenticated - remove auth header
- KSR::AUTH.consume_credentials() if !KSR.is_method_in("RP")
- end
- # if caller is not local subscriber, then check if it calls
- # a local destination, otherwise deny, not an open relay here
- if !KSR.is_myself_furi() && !KSR.is_myself_ruri() then
- KSR::SL.sl_send_reply(403, "Not relaying")
- exit
- end
- return
- end
- def ksr_route_natdetect()
- KSR.force_rport()
- if KSR::NATHELPER.nat_uac_test(19) > 0 then
- if KSR.is_REGISTER() then
- KSR::NATHELPER.fix_nated_register()
- elsif KSR::SIPUTILS.is_first_hop() > 0 then
- KSR::NATHELPER.set_contact_alias()
- end
- KSR.setflag($FLT_NATS)
- end
- return
- end
- def ksr_route_natmanage()
- if KSR::SIPUTILS.is_request() > 0 then
- if KSR::SIPUTILS.has_totag() > 0 then
- if KSR::RR.check_route_param("nat=yes") > 0 then
- KSR.info("Natmanage - nat=yes")
- KSR.setbflag($FLB_NATB)
- end
- end
- end
- #KSR.info("Natmanage - returning if NAT flags set")
- return if !KSR.isflagset($FLT_NATS) and !KSR.isbflagset($FLB_NATB)
- #KSR.info("Natmanage - RTPPROXY from here on")
- KSR::RTPPROXY::RTPPROXY_manage("co");
- if KSR::SIPUTILS.is_request() > 0 then
- if !KSR::SIPUTILS.has_totag() then
- if KSR::TMX.t_is_branch_route() > 0 then
- KSR::RR.add_rr_param(";nat=yes")
- end
- end
- end
- if KSR::SIPUTILS.is_reply() > 0 then
- if KSR.isbflagset($FLB_NATB) then
- KSR::NATHELPER.set_contact_alias()
- end
- end
- return
- end
- def ksr_route_dlguri()
- KSR::NATHELPER.handle_ruri_alias() if !KSR.isdsturiset()
- return
- end
- def ksr_branch_manage()
- KSR.dbg("new branch [#{KSR::PV.get("$T_branch_idx")}] to #{KSR::PV.get("$ru")}\n")
- ksr_route_natmanage()
- return
- end
- def ksr_onreply_manage()
- scode = KSR::PV.get("$rs");
- KSR.dbg("Reply status code is #{scode}")
- ksr_route_natmanage() if scode > 100 and scode <= 299
- return
- end
- def ksr_reply_route()
- #scode = KSR::PV.get("$rs");
- return
- end
- def ksr_onsend_route()
- return
- end
- def ksr_failure_manage()
- ksr_route_natmanage()
- return if KSR::TM.t_is_canceled() > 0
- return
- end
- def ksr_dialog_event(evname)
- KSR.info("===== dialog module triggered event: #{evname}");
- return
- end
- def ksr_tm_event(evname)
- KSR.info("===== TM module triggered event: #{evname}");
- return
- end
- def ksr_route_sipout()
- return if KSR.is_myself_ruri()
- KSR::HDR.append("P-Hint: outbound\r\n")
- ksr_route_relay()
- exit
- end
- def ksr_route_registrar()
- return if !KSR.is_REGISTER()
- if KSR.isflagset($FLT_NATS) then
- KSR.setbflag($FLB_NATB)
- # do SIP NAT pinging
- KSR.setbflag($FLB_NATSIPPING)
- end
- KSR.info("saving loc")
- if KSR::REGISTRAR.save("location", 0).to_i < 0 then
- KSR::SL.sl_reply_error()
- end
- exit
- end
- def ksr_route_location()
- rc = KSR::REGISTRAR.lookup("location").to_i
- if rc < 0 then
- KSR::TM.t_newtran()
- if rc == -1 or rc == -3 then
- KSR::SL.sl_send_reply(404, "Not Found")
- exit
- elsif rc == -2 then
- KSR::SL.sl_send_reply(405, "Method Not Allowed")
- exit
- end
- end
- # when routing via usrloc, log the missed calls also
- KSR.setflag($FLT_ACCMISSED) if KSR.is_INVITE()
- ksr_route_relay()
- exit
- end
|