######## NAT Traversal module - signaling functions ######## #!ifndef NATHELPER_LOADED loadmodule "nathelper.so" #!trydef NATHELPER_LOADED #!endif modparam("nathelper", "received_avp", "$avp(AVP_RECV_PARAM)") modparam("nathelper", "sipping_from", "sip:registrar@MY_HOSTNAME") #!ifdef WEBSOCKETS_ROLE #!trydef KZ_NAT_DETECT 83 #!else #!trydef KZ_NAT_DETECT 19 #!endif #!trydef KZ_NAT_FIX_SDP_REQUEST 1 #!trydef KZ_NAT_FIX_SDP_REPLY 1 #!trydef KZ_NAT_SDP_TEST 8 #!trydef KZ_NAT_SDP_FIX 10 kazoo.nat_fix_sdp_request = KZ_NAT_FIX_SDP_REQUEST descr "performs request sdp replacement of private addresses" kazoo.nat_fix_sdp_reply = KZ_NAT_FIX_SDP_REPLY descr "performs reply sdp replacement of private addresses" ####### NAT Traversal Logic ######## route[NAT_SDP] { if( has_body("application/sdp")) { if( nat_uac_test(KZ_NAT_SDP_TEST)) { xlog("L_DEBUG", "$ci|log|applying sdp nat fix\n"); $var(ret) = fix_nated_sdp(KZ_NAT_SDP_FIX); xlog("L_DEBUG", "$ci|log|result of applying sdp nat fix is $var(ret)\n"); } else if( is_method("INVITE") && !isflagset(FLAG_INTERNALLY_SOURCED) && is_audio_on_hold()) { xlog("L_DEBUG", "$ci|log|applying sdp nat fix for held channel\n"); $var(ret) = fix_nated_sdp(KZ_NAT_SDP_FIX); xlog("L_DEBUG", "$ci|log|result of applying sdp nat fix for held channel is $var(ret)\n"); } } } route[NAT_DETECT] { if($sel(cfg_get.kazoo.nat_fix_sdp_request) == 1) { route(NAT_SDP); } if ($Rp == "5080") { setflag(FLAG_SKIP_NAT_CORRECTION); xlog("L_DEBUG", "$ci|log|skipping nat correction on PORT 5080\n"); } else { if (is_present_hf("Record-Route")) { $var(i) = 0; $var(rr_count) = $rr_count; while($var(i) < $var(rr_count)) { $var(rr_base) = $(hdr(Record-Route)[$var(i)]); $var(rr_idx) = 0; $var(rr) = $(var(rr_base){s.select,$var(rr_idx),,}); while($var(rr) != $null && $var(rr) != "") { $var(i) = $var(i) + 1; if (!is_myself("$(var(rr){nameaddr.uri})")) { setflag(FLAG_SKIP_NAT_CORRECTION); xlog("L_DEBUG", "$ci|log|skipping nat correction on record-route $(var(rr){nameaddr.uri})\n"); } $var(rr_idx) = $var(rr_idx) + 1; $var(rr) = $(var(rr_base){s.select,$var(rr_idx),,}); } } } } if (isflagset(FLAG_SKIP_NAT_CORRECTION)) { xlog("L_DEBUG", "$ci|log|skipping nat detection\n"); return; } force_rport(); if(nat_uac_test(KZ_NAT_DETECT)) { xlog("L_DEBUG", "$ci|log|detected nat request\n"); setflag(FLT_NATS); if (!is_method("REGISTER")) { if(is_first_hop()) set_contact_alias(); } } } route[NAT_MANAGE] { if( is_reply() && $sel(cfg_get.kazoo.nat_fix_sdp_reply) == 1) { route(NAT_SDP); } if ( is_request() && isflagset(FLAG_INTERNALLY_SOURCED)) { xlog("L_DEBUG", "$ci|log|INTERNAL AND REQUEST => SET FLB_NATB\n"); setbflag(FLB_NATB); } if ( is_request() && has_totag() ) { xlog("L_DEBUG", "$ci|log|TOTAG AND REQUEST => SET FLB_NATB\n"); setbflag(FLB_NATB); } if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) { xlog("L_DEBUG", "$ci|log|NOT SETTING\n"); return; } if (is_reply()) { if(isflagset(FLT_NATS) || isbflagset(FLB_NATB)) { if(is_first_hop()) { if (!isflagset(FLAG_MANUAL_ALIAS)) { xlog("L_DEBUG", "$ci|log|MANAGE => SET CONTACT ALIAS\n"); set_contact_alias(); } } else { xlog("L_DEBUG", "$ci|log|MANAGE => NOT FIRST HOP $mb\n"); } } } } # vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab