OpenSER scripting

Norman Brandinger

Edited by

Norman Brandinger


Table of Contents

1. Introduction
2. The M4 Macro Processor
3. Keep backup copies of your configuration files
4. Process M4 .m4 files into OpenSER .cfg files
5. Place debugging code in your configuation file
6. Example of a route[ROUTE_REGISTER]
7. Example of a route[ROUTE_CHECK_STATUS]

1. Introduction

The OpenSER configuration file (openser.cfg) is more than just a typical configuration file. It combines both static settings and a dynamic programming environment.

When you create the configuration file, you will spend more time “programming” then setting initialization variables. It may be easier for you to consider the configuration file (openser.cfg) as "program". In fact, “openser.cfg” is a program that is executed for each message received by the Open SIP Express Router (OpenSER).

Standard programming practices should be followed when creating openser.cfg. By following the four rules below you will save time and energy while writing and debugging openser.cfg.

  • The most important thing that you can do is to document the code you write. Don't question this statement, just do it! All text after a hash mark, pound sign or whatever you want to call the “#” will be treated as a comment.

  • Avoid unnecessarily complex programming constructs.

  • Be consistent with your naming conventions, indentation and statement constructs.

  • Structure as much as possible your configuration logic by using routes block as functions (via return codes and flags).

2. The M4 Macro Processor

openser.cfg” files, other than for very uncomplicated scenarios or testing can easily become unwieldy. We have found that using the M4 preprocessor has made our “openser.cfg” files more readable, easier to maintain and less error prone.

What is M4 ?

M4 is a macro processor, in the sense that it copies its input to the output, expanding macros as it proceeds. Macros are either builtin or user-defined, and can take any number of arguments. Besides just doing macro expansion, M4 has builtin functions for including named files, running UNIX commands, doing integer arithmetic, manipulating text in various ways, recursion, etc... M4 can be used either as a front-end to a compiler, or as a macro processor in its own right.

(copied from the M4 man page)

As a new M4 user, it's best to start of with simple defines and work your way up to more complex configurations. We use the general programming style that ALL M4 definitions are in UPPERCASE.

Let's create an M4 file that will hold settings specific to the server that OpenSER is running on. Since we will have multiple servers with OpenSER, we want to keep server specific settings isolated in their own file.

Note

Note that “by convention” all files we intend to use M4 with will have a suffix of “.m4”.

We will call the file “local.m4”. It will contain the following definitions on a production machine:


# Production Database definitions
define(`OPENSER_USER',`PRODUCTION_USER')
define(`OPENSER_PW',`PRODUCTION_PASSWORD')

# Production IP Address, Port and Hostname definitions
define(`OPENSER_IP', `xxx.xxx.xxx.xxx')
define(`OPENSER_PORT', `5060')
define(`OPENSER_HOST', `openser.production.com')
define(`OPENSER_NAME', `OpenSER Production System')

		

On a development machine, the “local.m4” file might contain:


# Development Database definitions
define(`OPENSER_USER',`DEVELOPMENT_USER')
define(`OPENSER_PW',`DEVELOPMENT_PASSWORD')

# Development IP Address, Port and Hostname definitions
define(`OPENSER_IP', `yyyy.yyyy.yyyy.yyyy')
define(`OPENSER_PORT', `5060')
define(`OPENSER_HOST', `openser.development.com')
define(`OPENSER_NAME', `OpenSER Development System')

		

Next, we need to create the OpenSER configuration file “openser.m4”. For example, “openser.m4” might contain:

#----------------------------
# Global Variable Definitions
#----------------------------
#
#----------------------------------------------------------------
# The port parameter specifies which TCP/UDP port OPENSER should 
# run. The default is 5060 according to RFC 3261.
#----------------------------------------------------------------
port=OPENSER_PORT
#----------------------------------------------------------------------
# The listen parameter specifies which interface / IP address OPENSER
# runs. By default, OPENSER listens on all interfaces. 
# One can restrict OPENSER to run on IP addresses (e.g. 192.168.1.1), 
# hostname (e.g. sip.some.domain) or interface name (e.g. eth0).
# Multiple entries are accepted by specifying more than one.
# (e.g. listen="eth0" "192.168.1.1" "sip.some.domain")
# Protocol and port number are accepted as well (e.g. tcp:*:5066)
#----------------------------------------------------------------------
listen="OPENSER_IP"
#-----------------------------------------------------------------
# Accounting Parameters
#-----------------------------------------------------------------
modparam("acc", "db_url", "mysql://OPENSER_USER:OPENSER_PW@OPENSER_DB_SERVER/OPENSER_DATABASE")
		

M4 defines can be specified in both “openser.m4” as well as “local.m4”.

M4 defines can be used to create easy to read FLAG variables. For example, in your “openser.m4” file you could write setflag(FLAG_NAT) instead of setflag(6). The output from the M4 processor will take “FLAG_NAT” and replace it with “6”.

Below is an example of how you can define FLAG variables.

		
#------------------------------
# Flags
#------------------------------
define(`FLAG_DEBUG',         1)
define(`FLAG_ANONYMOUS',     2)
define(`FLAG_VM',            3)
define(`FLAG_NAT_CALLER',    4)
define(`FLAG_NAT_CALLEE',    5)
define(`FLAG_ACC',           6)
define(`FLAG_ACC_DB',        7)
define(`FLAG_MISSED_CALL',   8)
define(`FLAG_NAT_DETECTED',  9)
define(`FLAG_CALL_QUEUE',   10)
define(`FLAG_NAT_PING',     11)
define(`FLAG_FWD_BLIND',    12)
define(`FLAG_FWD_ALLOWED',  13)
define(`FLAG_FWD_BUSY',     14)
define(`FLAG_FWD_NOANSWER', 15)
define(`FLAG_FAILURE_ROUTE',16)

		

M4 defines can also be used to create easy to read Route block names. If you have ever wondered if you should call route(6) or route(13), use these definitions and write route(ROUTE_INVITE) or route(ROUTE_REGISTER).

Below is an example of defining easy to remember names for route blocks associated with SIP METHODS.

		
#------------------------------------
# ROUTES - METHODS
#------------------------------------
define(`ROUTE_ACK',                2)
define(`ROUTE_BYE',                3)
define(`ROUTE_CANCEL',             4)
define(`ROUTE_INFO',               5)
define(`ROUTE_INVITE',             6)
define(`ROUTE_MESSAGE',            7)
define(`ROUTE_NOTIFY',             8)
define(`ROUTE_OPTIONS',            9)
define(`ROUTE_PRACK',             10)
define(`ROUTE_PUBLISH',           11)
define(`ROUTE_REFER',             12)
define(`ROUTE_REGISTER',          13)
define(`ROUTE_SUBSCRIBE',         14)
define(`ROUTE_UPDATE',            15)

		

Below is an example of defining easy to remember names for route blocks that might perform specific functions within your configuration file

		
#------------------------------------
# ROUTES - LOCAL
#------------------------------------
define(`ROUTE_RELAY',              1)
define(`ROUTE_RELAY_ONREPLY',      1)
define(`ROUTE_RELAY_FAILURE',      1)

define(`ROUTE_VM_DND',            16)
define(`ROUTE_PSTN_AUTH',         17)
define(`ROUTE_STATUS_DEBUG',      18)
define(`ROUTE_NAT_DETECTION',     19)
define(`ROUTE_PSTN',              20)
define(`ROUTE_CALL_FORWARD',      21)
define(`ROUTE_DEBUG_FLAGS',       22)

		

Warning

Remember that if use the same “number” in two different ROUTE defines, your configuration file will most likely fail. For example, do not define both “ROUTE_INVITE,3” and “ROUTE_CANCEL,3” unless you understand the implications and side effects.

M4 defines can be used to provide easy to remember names for servers that OpenSER can communicate with. For example:

		
#---------------------------------------------
# Voicemail Server
#---------------------------------------------
define(`VM_NAME',     `Voice Mail')
define(`VM_HOSTNAME', `voicemail.example.com')
define(`VM_IP',       `xxx.xxx.xxx.xxx')
define(`VM_PORT',     `5060')

		

We also use M4 definitions for conditionals, for example:


#------------------
# Conditionals
#------------------
define(`FALSE', -1)
define(`EXIT',  0)
define(`TRUE',  1)

define(`NO',     0)
define(`YES',    1)

		

When defining variables try to be consistent. Set up some standard naming convention. It doesn't really matter if you want to use FLAG_BREAK, BREAK or BREAK_FLAG as long as you use the same standard throughout your “.m4” file(s).

Please set up a standard naming convention and try so stick to it. It will save you time, trouble and make your coding faster and less error prone.

3. Keep backup copies of your configuration files

Always keep backup copies of your “.m4” and “.cfg” files around. The backups are not just for archival purposes, but to easily back off changes.

Anyone that has made changes to an original “.cfg” file and wanted to quickly back out the changes will find this approach valuable.

We name our “.m4” and “.cfg” files “openser1a.m4”, “openser1a.cfg”, “openser2a.m4”, “openser2a.cfg”... etc. The point here isn't the naming convention, it is keeping a history of your “.m4” and “.cfg” files.

4. Process M4 “.m4” files into OpenSER “.cfg” files

We follow a simple naming convention for our “openser.m4” files. The following PERL script will create “.cfg” file from the “.m4” files.


#!/usr/bin/perl

$x = $ARGV[0];

print "OPENSER config file m4 preprocessor\n";
print "source:      /usr/local/etc/openser/openser$x.m4\n";
print "destination: /usr/local/etc/openser/openser$x.cfg\n";

`m4 /usr/local/etc/openser/local.m4 /usr/local/etc/openser/openser$x.m4 > /usr/local/etc/openser/openser$x.cfg`;

`cp /usr/local/etc/openser/openser$x.cfg /usr/local/etc/openser/openser.cfg`;

		

local.m4” contains machine and/or OpenSER instance specific settings “openser1a.m4” contains the source configuration file. Both files contain M4 defines

If we name the above PERL script “make_openser”, then the command


make_openser 1a

		

will produce “openser1a.cfg” (from “local.m4” and “openser1a.m4”) with all of the M4 macro definitions processed. In addition, the script will copy “openser1a.cfg” to “openser.cfg”. This step makes it a little easier to start OpenSER with the newly created configuration file without the need to modify “openserctl”.

Depending upon your situation, you can either use “openser1a.cfg” when starting OpenSER from the command lineas shown below:


openser -f /usr/local/etc/openser1a.cfg

		

If you make a change to “openser.cfg” while OpenSER is running, you will have to restart OpenSER before the new configuration file will take effect. There is no “reload” command that will update a running OpenSER with a new configuration.

If you restart OpenSER when “syn_branch=yes” is specified in your “openser.cfg”, restarting OpenSER may result in a failed on-going transaction.

5. Place debugging code in your configuation file

Programmer note: We are aware that there are many different ways to solve a particular problem. We are not suggesting that our coding preferences or naming standards are right for you. We are only presenting a solution that works for us and will hopefully work for you.

We have placed the following code right after the start of route[0], the primary route block in our openser.cfg. This code sets up our debugging environment.


route {

  route(ROUTE_DEBUG_FLAGS);

		

At the bottom of our configuration file we have placed the following code:


#--------------------------------------------------------------
# ROUTE DEBUG FLAGS
#--------------------------------------------------------------
route[ROUTE_DEBUG_FLAGS] {
  resetflag(FLAG_DEBUG);
  #------------------------------------------------------------
  # Methods that will have debugging turned on
  #------------------------------------------------------------
       if (is_method("ACK"))           { resetflag(FLAG_DEBUG); }
  else if (is_method("BYE"))           { setflag(FLAG_DEBUG); }
  else if (is_method("CANCEL"))        { setflag(FLAG_DEBUG); }
  else if (is_method("INVITE"))        { setflag(FLAG_DEBUG); }
  else if (is_method("OPTIONS"))       { setflag(FLAG_DEBUG); }
  else if (is_method("PUBLISH"))       { setflag(FLAG_DEBUG); }
  else if (is_method("REGISTER"))      { resetflag(FLAG_DEBUG); }
  else if (is_method("MESSAGE"))       { setflag(FLAG_DEBUG); }
  else if (is_method("NOTIFY"))        { setflag(FLAG_DEBUG); }
  else if (is_method("SUBSCRIBE"))     { setflag(FLAG_DEBUG); }
  else if (is_method("INFO"))          { setflag(FLAG_DEBUG); }
  else if (is_method("PRACK"))         { setflag(FLAG_DEBUG); }
  else if (is_method("REFER"))         { setflag(FLAG_DEBUG); }
  else {
     setflag(FLAG_DEBUG);
  };
}

		

The first thing we do is call the route block called ROUTE_DEBUG_FLAGS. This is much more readable than writing route(22). Once we enter the route block the FLAG_DEBUG variable is turned off. We could have written resetflag(1) instead, but the whole object is to make the code more readable. Some people will make the assumption that FLAG_DEBUG starts out in the reset (or off) condition, why tempt fate. We next determine which METHODs we want to print debugging information for. If the SIP message currently being processed matches one of the conditions then we either “set” or “reset” the debugging flag. The debugging flag will be used throughout the configuration file to print information regarding the processing of the SIP message. In the above example, we do not want to print out any debugging information for ACK or REGISTER messages.

SIP traces are a valuable tool for tracking what happens when OpenSER communications to the external world. It is equally important to track how OpenSER is processing each message that it receives. Unfortunately, SIP traces cannot track anything internal to OpenSER. This is why putting debugging information in the configuration file is so important.

Once the initial debugging environment has been set up, we can enclose our debugging login within an if (isflagset(FLAG_DEBUG)) { }; statement. For example:


#--------------------------
# Log debugging information
#--------------------------
if (isflagset(FLAG_DEBUG))
    xlog("L_NOTICE", "$mi route[$rm][0] $fu -> $ru START PROCESSING MESSAGE\n");

		

Note that the curly braces “{}” are not required if there is only a single statement associated with the “if”.

$mi is the SIP message ID and we find it useful to use it to match up log messages as processing flows through OpenSER.

$rm is the METHOD associated with the SIP message.

$fu is the From URI.

$ru is the request's URI.

We have found that “xlog” along with the debugging flag provides easy access to more than enough information to help track the execution flow and content of each message that OpenSER processes.

Place debugging code "EVERYWHERE" throughout your “.cfg” file.

You will thank yourself for when you receive unexpected results and wonder what processing within OpenSER has taken place.

In the route block that you use to authenticate REGISTER requests (you do have a route block specific to REGISTER requests don't you ?) You might want to print a descriptive log record out along with the SIP 403 Unknown domain (that is only visible using a SIP tracing tool). For example:


#--------------------------------------------------------------------
# Check for known domain(s)
#--------------------------------------------------------------------
if (!is_from_local()) {
   if (isflagset(FLAG_DEBUG))
      xlog("L_NOTICE",
	  "OPENSER_NAME: $mi route[$rm][ROUTE_REGISTER] $fu Unknown domain\n");
   sl_send_reply("403", "Unknown domain");
   return(FALSE);
};

		

Once you have completed debugging the REGISTER route block and don't want these messages in your log, just “resetflag(FLAG_DEBUG)” for “is_method("REGISTER")” instead of removing the debugging code from your “.m4” file. You will thank yourself the next time someone can't REGISTER and you need to debug the code again.

6. Example of a route[ROUTE_REGISTER]

		
#---------------------------------------------------------------------------
# ROUTE REGISTER
#---------------------------------------------------------------------------
route[ROUTE_REGISTER] {

  #----------------------------------------------------------------------
  # NAT Detection
  #----------------------------------------------------------------------
  if (!search("^Contact:[ ]*\*") && nat_uac_test("19")) {
    setflag(FLAG_NAT_CALLER);
    setflag(FLAG_NAT_PING);
    fix_nated_register();
    force_rport();
  };

  #----------------------------------------------------------------------
  # Let the UA know we are working on their request - they shouldn't 
  # send retransmissions
  #----------------------------------------------------------------------
  sl_send_reply("100", "Trying");

  #--------------------------------------------------------------------
  # Check for known domain(s)
  #--------------------------------------------------------------------
  if (!is_from_local()) {
    if (isflagset(FLAG_DEBUG))
        xlog("L_NOTICE", "OPENSER_NAME: $mi route[$rm][ROUTE_REGISTER] \
        $fu Unknown domain\n");
    sl_send_reply("403", "Unknown domain");
    return(FALSE);
  };

  #--------------------------------------------------------------------
  # Check to see that the user has not been disabled
  #--------------------------------------------------------------------
  if (is_user_in("From", "disabled")) {
    if (isflagset(FLAG_DEBUG))
        xlog("L_NOTICE", "OPENSER_NAME: $mi route[$rm][ROUTE_REGISTER] \
        $fu Your account has been disabled\n");
    sl_send_reply("403", "Your account has been disabled");
    exit;
  };
  if (is_user_in("To", "disabled")) {
    if (isflagset(FLAG_DEBUG))
        xlog("L_NOTICE", "OPENSER_NAME: $mi route[$rm][ROUTE_REGISTER] \
        $tu Your account has been disabled\n");
    sl_send_reply("403", "Your account has been disabled");
    return(FALSE);
  };

  if (!is_user_in("From", "noauth")) {
  #--------------------------------------------------------------------
  # Prohibit attempts to grab someone else's To address using valid credentials
  #--------------------------------------------------------------------
  if (!www_authorize("", "subscriber")) {
    if (isflagset(FLAG_DEBUG))
        xlog("L_NOTICE", "OPENSER_NAME: $mi route[$rm][ROUTE_REGISTER] \
        $fu Authorization for $fu ($si) requested\n");
    www_challenge("", "0");
    return(FALSE);
  } else {
    if (isflagset(FLAG_DEBUG))
       xlog("L_NOTICE","OPENSER_NAME: $mi route[$rm][ROUTE_REGISTER] \
       $fu Authorization OK\n");
  };

  #--------------------------------------------------------------------
  # check_to
  #--------------------------------------------------------------------
  if (!check_to()) {
    if (isflagset(FLAG_DEBUG))
        xlog("L_NOTICE", "OPENSER_NAME: $mi route[$rm][ROUTE_REGISTER] \
        $fu -> $ru REPLY 401 - Unauthorized check_to() failed\n");
    sl_send_reply("401", "Unauthorized");
    return(FALSE);
  };

  consume_credentials();
  };

  #--------------------------------------------------------------------
  # Authenticated request, update location table
  #--------------------------------------------------------------------
  if (!save("location")) {
    if (isflagset(FLAG_DEBUG))
        xlog("L_NOTICE", "OPENSER_NAME: $mi route[$rm][ROUTE_REGISTER] \
        $fu save(location) Failed\n");
    sl_reply_error();
    return(FALSE);
  } else {
    if (isflagset(FLAG_DEBUG))
        xlog("L_NOTICE", "OPENSER_NAME: $mi route[$rm][ROUTE_REGISTER] \
        $fu save(location)OK\n");
    m_dump();
  };

  return(TRUE);
}
		
		

7. Example of a route[ROUTE_CHECK_STATUS]

This example shows how a printable log record from the SIP status. Obviously, this route block should only be called from a location within your configuration file where the “t_check_status()” function produces meaningful results.


#-----------------------------------------------------------------
# ROUTE CHECK STATUS
#-----------------------------------------------------------------
route[ROUTE_CHECK_STATUS] {
  if (isflagset(FLAG_DEBUG)) {
     if (t_check_status("100")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 100 Trying\n");
     } else if (t_check_status("180")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 180 Ringing\n");
     } else if (t_check_status("181")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 181 Call Is Being Forwarded\n");
     } else if (t_check_status("182")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 182 Queued\n");
     } else if (t_check_status("183")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 183 Session Progress\n");
     } else if (t_check_status("200")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 200 OK\n");
     } else if (t_check_status("202")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 202 Accepted\n");
     } else if (t_check_status("300")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 300 Multiple Choices $ct\n");
     } else if (t_check_status("301")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 301 Moved Permanently $ct\n");
     } else if (t_check_status("302")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 302 Moved Temporarily $ct\n");
     } else if (t_check_status("305")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 305 Use Proxy\n");
     } else if (t_check_status("380")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 380 Alternative Service\n");
     } else if (t_check_status("400")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 400 Bad Request\n");
     } else if (t_check_status("401")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 401 Unauthorized\n");
     } else if (t_check_status("402")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 402 Payment Required\n");
     } else if (t_check_status("403")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 403 Forbidden\n");
     } else if (t_check_status("404")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 404 Not Found\n");
     } else if (t_check_status("405")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 405 Method Not Allowed\n");
     } else if (t_check_status("406")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 406 Not Acceptable\n");
     } else if (t_check_status("407")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 407 Proxy Authentication Required\n");
     } else if (t_check_status("408")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 408 Request Timeout\n");
     } else if (t_check_status("409")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 409 Conflict\n");
     } else if (t_check_status("410")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 410 Gone\n");
     } else if (t_check_status("411")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 411 Length Required\n");
     } else if (t_check_status("412")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 412 Conditional Request Failed\n");
     } else if (t_check_status("413")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 413 Request Entity Too Large\n");
     } else if (t_check_status("414")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 414 Request-URI Too Long\n");
     } else if (t_check_status("415")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 415 Unsupported Media Type\n");
     } else if (t_check_status("416")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 416 Unsupported URI Scheme\n");
     } else if (t_check_status("420")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 420 Bad Extension\n");
     } else if (t_check_status("421")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 421 Extension Required\n");
     } else if (t_check_status("422")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 422 Session Interval Too Small\n");
     } else if (t_check_status("423")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 423 Interval Too Brief\n");
     } else if (t_check_status("429")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 429 Provide Referrer Identity\n");
     } else if (t_check_status("480")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 480 Temporarily Unavailable\n");
     } else if (t_check_status("481")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 481 Call Leg/Transaction Does Not Exist\n");
     } else if (t_check_status("482")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 482 Loop Detected\n");
     } else if (t_check_status("483")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 483 Too Many Hops\n");
     } else if (t_check_status("484")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 484 Address Incomplete\n");
     } else if (t_check_status("485")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 485 Ambiguous\n");
     } else if (t_check_status("486")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 486 Busy Here\n");
     } else if (t_check_status("487")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 487 Busy Here; Request Terminated\n");
     } else if (t_check_status("488")) {
        xlog("L_NOTICE", "OPENSER_NAME: $mi $rm $fu -> $ru status 488 Not Acceptable Here\n");
     } else if (t_check_status("489")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 489 Bad Event\n");
     } else if (t_check_status("491")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 491 Request Pending\n");
     } else if (t_check_status("493")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 493 Undecipherable\n");
     } else if (t_check_status("494")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 494 Security Agreement Required\n");
     } else if (t_check_status("500")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 500 Server Internal Error\n");
     } else if (t_check_status("501")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 501 Not Implemented\n");
     } else if (t_check_status("502")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 502 Bad Gateway\n");
     } else if (t_check_status("503")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 503 Service Unavailable\n");
     } else if (t_check_status("504")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 504 Server Timeout\n");
     } else if (t_check_status("505")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 505 Version Not Supported\n");
     } else if (t_check_status("513")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 513 Message Too Large\n");
     } else if (t_check_status("580")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 580 Precondition Failure\n");
     } else if (t_check_status("600")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 600 Busy Everywhere\n");
     } else if (t_check_status("603")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 603 Decline\n");
     } else if (t_check_status("604")) {
        xlog("L_NOTICE",
        "OPENSER_NAME: $mi $rm $fu -> $ru status 604 Does Not Exist Anywhere\n");
     } else if (t_check_status("606")) {
        xlog("L_NOTICE",
       "OPENSER_NAME: $mi $rm $fu -> $ru status 606 Not Acceptable\n");
     } else {
        xlog("L_NOTICE", "OPENSER_NAME: $mi $rm $fu -> $ru status not listed\n");
     };
     xlog("L_NOTICE", "OPENSER_NAME: $mi $mb\n");
  };
}