[Devel] loose_route() incorrectly strict routing locally forwarded messages

Tavis P tavis.lists at galaxytelecom.net
Wed Apr 12 00:08:20 CEST 2006


I've been having a problem where ACK and BYE messages that are being
forwarded to another port on the local machine (where asterisk is
running for example) are being incorrectly handled by loose_route().
It seems to think it needs to use strict routing semantics (replacing
the RURI with that of the Route: header field value) however the message
is not structured to be strict routed so it causes local looping problems.

Using the same UA but altering the routing slightly such that the messge
is sent to a non-local different ip address (in which case the ACK/BYE
is of the same structure but has a different destination and tags/flags,
etc)) the loose_route() function properly classifies the ACK/BYE as
needing to be loose routed and everything works as expected

Attached is a stripped down openser config file that will exhibit the
problem i've encountered
The following lines will need modification:
- "seturi("sip:400 at 127.0.0.1:5080");"   - you will need to have some
local application (could be another openser that simply responds "200
OK"!) that will listen on another port locally
- "#seturi("sip:400 at some.other.system");"   - change to
some.other.system to some external system that will accept an INVITE and
initiate a dialog


Initially the script will route the call to the local host and you will
see in the log that loose_route() will treat the message using strict
route semantics even though the message does not classify
afterwards you can comment out the first seturi() command and uncomment
the second seturi command, make the same phone call and see that
loose_route() will properly classify the ACK and BYE messages


This was tested on the latest version of openser 1.0.0 stable checked
out of CVS on Friday April 7, 2006
UACs tested with this configuration: (All of which do not do strict routing)
Cisco 7960 W/Voice Software 7.5
Sipura SPA2100 W/Firmware 3.2.5d
Xlite 1105d


I've stored pcap and openser debug (level 99) traces of each situation
(local forward and external forward), they are available on request


thanks!
-------------- next part --------------
#!/usr/bin/perl
# Because i'm too lazy to change the default Jed commenting style
# ----------- global configuration parameters ------------------------

debug=99        # debug level 
#fork=yes
#log_stderror=no        # (cmd line: -E)

# Debug level to log memory information at
memlog=1

/* Uncomment these lines to enter debugging mode
fork=no
log_stderror=yes
*/


# Parameter to set alias hostnames for the server. It can be set many times, 
# each value being added in a list to match the hostname when "myself" is checked.
#
alias=127.0.0.1


# Syslog Name 
#
log_name="OpenSER"


# User and Group To Run SER As
#
user=openser
group=openser

#port=15061

# ------------------ module loading ----------------------------------
# Module Directory
mpath="/openser/lib/openser/modules"

#loadmodule "mysql.so"
#loadmodule "enum.so"
#loadmodule "exec.so"
#loadmodule "pike.so"
#loadmodule "permissions.so"
#loadmodule "domain.so" # needed by mediaproxy.so
#loadmodule "avpops.so"
#loadmodule "avp_radius.so"
#loadmodule "group_radius.so"
#loadmodule "avp.so"
loadmodule "sl.so"
#loadmodule "options.so"
loadmodule "tm.so"
#loadmodule "acc.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
#loadmodule "uri_db.so"
#loadmodule "usrloc.so"
#loadmodule "cpl-c.so"
#loadmodule "registrar.so"
#loadmodule "mediaproxy.so"
loadmodule "nathelper.so"
#loadmodule "diversion.so"
loadmodule "textops.so"
loadmodule "uri.so"
#loadmodule "auth.so"
#loadmodule "auth_db.so"
#loadmodule "auth_radius.so"
loadmodule "xlog.so"




# Stop nathelper from trying to connect to rtpproxy on startup
modparam("nathelper", "rtpproxy_disable", 1)
  






route

{


    # -----------------------------------------------------------------
    # - Initial Sanity Checks -
    # messages with max_forwards==0, or excessively long requests
    # If its an ACK, we simply want to break, not respond.
    # -----------------------------------------------------------------
    if ( !mf_process_maxfwd_header("10") )
    {
        # Any messages that are not expecting a response don't need one
        if ( !is_method("ACK") )
        {
            sl_send_reply("483", "Too many hops");
        }

        xlog("L_WARN", "[$fU] Route{main}: Message Max-Forwards == 0");
        exit;
    }

    if ( msg:len >= max_len )
    {
        # Any messages that are not expecting a response don't need one
        if ( !is_method("ACK") )
        {
            sl_send_reply("513", "Message too big");
        }

        xlog("L_WARN", "[$fU] Route{main}: Message was too big");
        exit;
    }

    # -----------------------------------------------------------------
    # - Loose Route -
    # subsequent messages within a dialog should take the
    # path determined by record-routing
    # !! Going to have to keep an eye on this one as it may be open to abuse.
    # -----------------------------------------------------------------
    xlog("L_WARN", "[$fU] Route{main}; Destination URI Before loose_route() - [$du] - ");
    xlog("L_WARN", "[$fU] Route{main}: Before Loose routing..");
    if ( loose_route() )
    {
        xlog("L_WARN", "[$fU] Route{main}: Loose routing..");
        xlog("L_WARN", "[$fU] Route{main}; Destination URI After loose_route()- [$du] - ");


        # Send to outbound routing block
        route(10);
            
        exit;
    }


    route(10);
}
	



# ------------------------------------------------------------------------
# -[ Outbound Routing Block ]-
# ------------------------------------------------------------------------
route[10]
{
    xlog("L_WARN", "[$fU] Route{10}: Starting Outbound Routing Block.");

    xlog("L_WARN", "[$fU] Route{10}: Destination Set = [ $ds ]");

    if ( nat_uac_test("3") )
    {
        xlog("L_WARN", "[$fU] Route{main}: NAT Client - Fixing Contact and Forcing RPORT");
		  
        # Rewrite IP:PORT in Contact to match the recieved IP:PORT
        fix_nated_contact();
		  
        # Add "rport" to topmost via
        force_rport();
    }

    if ( method == "REGISTER" )
    {
        sl_send_reply("200", "Ok");
        exit;
    }
    
    
    if ( (method == "INVITE" || status =~ "200") )
    {
        xlog("L_WARN", "[$fU] Route{10}: INSIDE RECORD_ROUTING BLOCK");

        record_route();
    }
    
    
    if ( method == "INVITE" )
    {
	# I used asterisk running locally on port 5080, but it shouldn't matter in the slightest 
	# what you use, as long as it can respond to an INVITE with a "200 OK"
	# which will cause the UA to generate an ACK and then a BYE when it hangs up
	# that will exhibit the loose_route problem
        seturi("sip:400 at 127.0.0.1:5080");
	
	# using the same UA, and same logic but change the destination address to somthing non-local
	# makes the problem go away (as can be see by the xlog RURI statments surrounding loose_route()
        #seturi("sip:400 at some.other.system");

        t_on_reply("10");
    }

    # Route Message Out
    if ( !t_relay() )
    {
        xlog("L_WARN", "[$fU] Route{10}: t_relay error in Outbound Routing Block");
        sl_reply_error();
    }

}






onreply_route[10]
{

    xlog("L_WARN", "[$fU] OnReply_Route{10}: Starting");


    if ( nat_uac_test("1") )
    {
        xlog("L_WARN", "[$fU] OnReply_Route{10}: Client is behind NAT, altering message");
        force_rport();
        fix_nated_contact();
    }

}



More information about the Devel mailing list