[Serusers] MySQL, Accounting, PSTN Howto for all

mr barker mbcabalito at hotmail.com
Sun Jan 30 15:33:26 CET 2005


I have tried to send this via regular mail but it is not getting through ... 
so hence the hotmail.. hope that no one minds - Mr. B -

This has taken me quite some time to do this as I come from the Windows 
world.  Getting into the Linux world was quite a jump. (Now the rant)  First 
I would like to say that if some of the people in the Linux world had better 
documentation and most importantly keeping it current with the releases of 
software it would cut down on development time.

I use Konqueror for getting around the Linux System like using windows file 
explorer except better.  Open up a Konqueror and press F9 that will open a 
side bar of file management.  F4 is to open up a command shell in the 
directory that you are in.

This is based on the compiled from src Stable Version Of SER 8.14 Located 
Here ftp://ftp.berlios.de/pub/ser/0.8.14/src/  put this in the very root of 
the hard drive (this should keep all the paths correct … don’t change the 
name of the directory from sip_router)

I am running Fedora Core 3 Distribution Located here 
http://download.fedora.redhat.com/pub/fedora/linux/core/3/i386/iso/  there 
are 4 iso’s (FC3-i386-disc1-4.iso) which are bootable.
Make sure that MySQL is  enabled (make sure you check it off when 
installing) along with  PhPMySQL  I installed the Server Packages from the 
list.
I also installed Webmin located here http://www.webmin.com/ for remote 
access via a M$ machine.

Compiling the SRC code was a bit problematic for me (Note that there is an 
Install Doc error when making the bin distro you will need to go into the 
MakeFile and comment out the line at the bottom) it is only documentation.  
You will see this as soon as you use the gmake utility.

You will first need to edit the Makefile in the module of ACC

locate this line

# uncomment the next line if you wish to enable SQL accounting
DEFS+=-DSQL_ACC

This is the way it should look uncommented. Now save it. Lol

Open up a command shell in the sip_router directory.

Type the following

gmake all mode=debug exclude_modules="" modules

you will get some errors that are caused by the imcompleteness but not to 
worry you won’t be using them ..

It will should come up with “ser-0.8.14_linux_i386.tar.gz” you will need to 
do a find for this file because I have no idea where it places it so I use 
Konqueror to locate it. Then do a copy command to the Home directory so you 
have it for later also.

You will need to do some reading in the manual of SER so you will be 
familiar with the system. But here is a working ser.cfg using MySQL for 
accounting
You will need to create the data base using the shell script in the SBIN 
directory.
If you use “serctl start” and the pid file is not found then that means that 
there is an error in the ser.cfg
Yes I know that the code looks ugly however so does your dog ... just 
kidding … it is a work in progress as I work it down more … I hope that this 
will help a few folks out.

# This is a reworked script from someone else.
# $Id: ser.cfg A working MySQL, Accounting PSTN Reworked for 8.14
# By Peter Bjorklund / Mr. B .. may the code gods be pleased .. lol
#
# You will need the adjust the ports to suit you needs
#
#   xxx.xxx.xxx.xxx – this is your IP address  -  ex. 123.456.789.123
#   yyy.yyy.yyy.yyy – this is your PSTN GateWay address – ex. 
123.456.789.123
#
# ----------- global configuration parameters ------------------------

debug=3   # debug level (cmd line: -dddddddddd)
fork=yes
log_stderror=no   # (cmd line: -E)
memlog=3
listen=xxx.xxx.xxx.xxx # this is your IP address
sip_warning=yes

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

check_via=yes     # (cmd. line: -v)
dns=no           # (cmd. line: -r)
rev_dns=no      # (cmd. line: -R)
port=5060
children=4
fifo="/tmp/ser_fifo"

# ------------------ module loading ----------------------------------

loadmodule "/usr/local/lib/ser/modules/mysql.so"
loadmodule "/usr/local/lib/ser/modules/sl.so"
loadmodule "/usr/local/lib/ser/modules/tm.so"
loadmodule "/usr/local/lib/ser/modules/acc.so"
loadmodule "/usr/local/lib/ser/modules/rr.so"
loadmodule "/usr/local/lib/ser/modules/maxfwd.so"
loadmodule "/usr/local/lib/ser/modules/usrloc.so"
loadmodule "/usr/local/lib/ser/modules/registrar.so"
loadmodule "/usr/local/lib/ser/modules/exec.so"
loadmodule "/usr/local/lib/ser/modules/group.so"
loadmodule "/usr/local/lib/ser/modules/print.so"
loadmodule "/usr/local/lib/ser/modules/auth.so"
loadmodule "/usr/local/lib/ser/modules/auth_db.so"
loadmodule "/usr/local/lib/ser/modules/textops.so"
loadmodule "/usr/local/lib/ser/modules/uri.so"

# ----------------- setting module-specific parameters ---------------

# -- tm params --
modparam("tm", "fr_timer", 10 )
modparam("tm", "fr_inv_timer", 24 )
modparam("tm", "wt_timer", 10 )
# modparam("tm", "uac_from", "sip:daemon at iptel.org" )

# -- rr params --
# add value to ;lr param to make some broken UAs happy
modparam("rr", "enable_full_lr", 1)

# * 0 -- dont use mysql, 1 -- write_through, 2--write_back */

modparam("usrloc", "db_mode",   2)
modparam("usrloc", "timer_interval", 10)
modparam("usrloc", "db_url","mysql://ser:heslo@localhost/ser")

modparam("group", "db_url","mysql://ser:heslo@localhost/ser")

# -- auth params --

modparam("auth_db", "db_url","mysql://ser:heslo@localhost/ser")
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")

# -- acc params --
# report ACKs too for sake of completeness -- as we account PSTN
# destinations which are RR, ACKs should show up

modparam("acc", "db_url","mysql://ser:heslo@localhost/ser")
# modparam("acc", "log_missed_flag", 3)
modparam("acc", "log_level", 1)
modparam("acc", "db_flag", 1)
modparam("acc", "report_ack", 0)
modparam("acc", "log_fmt", "miocfsu")


############################################


# -------------------------  request routing logic -------------------
# main routing logic
route{
      /* ********* ROUTINE CHECKS  ********************************** */

      # filter too old messages
      if (!mf_process_maxfwd_header("10")) {
            log("LOG: Too many hops\n");
            sl_send_reply("483","Too Many Hops");
            break;
      };
      if ( msg:len > max_len ) {
            sl_send_reply("513", "Message too big");
            break;
      };
############# deal with local area code ################# you can replace 
the xxx with your area code

if (uri=~"sip:xxx[2-9][0-9][0-9][0-9][0-9][0-9][0-9]@.*") {
            strip(3);
      #     search_append("From: .*<sip:", "xxx");
      #     if (search("^To: .*<sip:xxx")) {
      #           replace("To: .*<sip:xxx", "To: <sip:");
      #     };
      };

      ################# billing ###########################

      if (method=="INVITE" || method=="BYE") {
            setflag(1);
            setflag(2); # yes I use this flag for debuging
      };

      /* ********* RR ********************************** */

      /* Do strict routing if route headers present */

      #if (loose_route()) { t_relay(); break; }; # do not use this format
      # instead just use this

loose_route();

      /* ********* DIVERSION ********************************** */
      /* apply all diversions before we proceed with processing of
         requests for us
      */
##########  You can adjust the Diviersions to your needs ###################
      /* IM gateway diversions */
      #if (uri=~"sip:.*@icq\yourdomainname\.com"
      #           | uri=~"sip:.*@msn\.yourdomainname\.com"
      #           | uri=~"sip:.*@aim\.yourdomainname\.com"
      #           | uri=~"sip:.*@yahoo\.yourdomainname\.com" ) {
      #     append_hf("P-hint: IMGW\r\n");
      #     if (!t_relay("xxx.xxx.xxx.xxx", "5070")) {
      #           sl_reply_error();
      #     };
      #     break;
      # };

      /* divert voicemail requests */
      #if (uri=~"mail\.yourdomainname\.com" | uri=~":5066"| uri=~":6060") {
      #     sethost("yourdomainname.com");
      #     append_hf("P-hint: VOICEMAIL\r\n");
      #     if ( !t_relay("mail.iptel.org", "6060")) {
      #           sl_reply_error();
      #     };
      #     break;
      # };

      /* ********* RR ********************************** */

      # look at whether we need record-routing;
      # - we need it for calls  from gateways (otherwise, subsequent
      #   requests from the other # party will attempt to contact gateway
      #     directly through blocked ports)
      # - we need it for Windows Messanger's IM sessions to cross
      #   some firewalls -- we force all MESSAGEs to go via our server
      #   to avoid blocking port numbers (some firewalls can do
      #   standard SIP but are puzzled by Microsoft's use of obsoleted
      #   IM session model)
      # - some other places may decide to set the record-routing
      #   flag (2 chosen) too; particularly, INVITEs to our gw

      if ( (src_ip==yyy.yyy.yyy.yyy & method=="INVITE") || method=="MESSAGE" 
|| method=="INFO")  {
            setflag(2);
      };

      /*  *********  check for requests targeted out of our domain... 
******* */
      # sign of our domain: there is @ (username), :
      # (nothing) or . (host) in front of our domain name     ;
      # if none of these cases matches, proceed with proessing of
      # outbound requests in route[2]
      if (!(uri=~"[@:\.]yourdomainname\.com([;:].*)*"
                  # ... some phones put IP address in URI instead ...
                  | uri=~"[@:\.]xxx\.xxx\.xxx\.xxx([;:].*)*"
                  # ... and we serve our gateway too (we RR requests to it, 
so that
                  # its address may show up in subsequent requests after
                  # rewriteFromRoute
                  | uri=~"@xxx\.xxx\.xxx\.xxx([;:].*)*" )) {
            route(2);
            break;
      };

      /* ************ requests for our domain ********** */

      /* now, the request is for sure for our domain */
      # registers always MUST be authenticated to
      # avoid stealing incoming calls

      if (method=="REGISTER") {

            # Make sure that user's dont register infinite loops
            # (note: does not match with folded lines)
            if (search("^(Contact|m): 
.*@(xxx\.xxx\.xxx\.xxx|yourdomainname\.com)")) {
                  log(1, "LOG: alert: someone trying to set 
aor==contact\n");
                  sl_send_reply("476", "No Server Address in Contacts 
Allowed" );
                  break;
            };

            # prohibit attempts to grab someone else's To address
            # using  valid grp; the only exception is the user
            # 'replciator' permitted to generate 3-rd party registrations

             if (!www_authorize("yourdomainname.com" /* realm */,
                                          "subscriber" /* table name */ )) {
                  # challenge if none or invalid grp
                  www_challenge(    "yourdomainname.com" /* realm */,
                                          "0" /* no qop -- some phones can't 
deal                                       with it */);
                  break;
             };

            if (!is_user("replicator") & !check_to()) {
                  log("LOG: To Cheating attempt\n");
                  sl_send_reply("403", "That is ugly -- use To=id next 
time");
                  break;
            };
            # it is an authenticated request, update Contact database now
            if (!save("location")) {
                  sl_reply_error();
            };
            /* XXX not tested yet
            t_replicate("bat.iptel.org", "5060");
            */
            break;
      };

            ###############deny calls without autorization#################

            if (!(src_ip==xxx.xxx.xxx.xxx | src_ip==yyy.yyy.yyy.yyy| 
method==ACK | method=="CANCEL" )) {
                  if (!proxy_authorize(   "yourdomainname.com" /* realm */,
                                          "subscriber" /* table name */))  {
                  proxy_challenge( "yourdomainname.com" /* realm */, "0" /* 
no qop */ );
                        break;
                  # let's check from=id ... avoids accounting confusion
                  } else if (method=="INVITE" & !check_from()) {
                        log("LOG: From Cheating attempt\n");
                        sl_send_reply("403", "That is ugly -- use From=id 
next time (gw)");
                        break;
                  };
            };

      /* some UACs might be fooled by Contacts our UACs
         generate to make MSN happy (web-im, e.g.) --
         tell its urneachable
      */
      if (uri=~"sip:daemon@" ) {
            sl_send_reply("410", "daemon is gone");
            break;
      };

      # various aliases (might use a database in future)
      lookup("aliases");
      # check again, if it is still for our domain after aliases
      # we have to include '.iptel.org' not to proceed to outbound
      # authentication for calls to mail.iptel.org and other hosts
      # served by us
      if ( !(uri=~"[@:\.]yourdomainname\.com([;:].*)*" |
            uri=~"[@:\.]xxx\.xxx\.xxx\.xxx([;:].*)*" )) {
            route(5);
            break;
      };

      # now check if it's about PSTN destinations through our gateway;
      # note that 1.... and 0.... is exempted for numerical non-gw 
destinations
      if (uri=~"sip:\+?[0-1][1-9][0-9]*@.*") {
            route(3);
            break;
      };

      # if relay
      if 
(uri=~"sip:\+?[2-9][0-9][0-9][2-9][0-9][0-9][0-9][0-9][0-9][0-9]@.*") {
            route(6);
            break;
      };

      # does the user wish redirection on no availability? (i.e., is he
      # in the voicemail group?) -- determine it now and store it in
      # flag 4, before we rewrite the flag using UsrLoc
      if (is_user_in("Request-Uri", "voicemail")) {
            setflag(4);
      } ;

      # native SIP destinations are handled using our USRLOC DB
      if (!lookup("location")) {
            # handle user which was not found ...
            route(4);
            break;
      };
      # check whether some inventive user has uploaded  gateway
      # contacts to UsrLoc to bypass our authorization logic
      if (uri=~"@yyy\.yyy\.yyy\.yyy([;:].*)*" ) {
            log(1, "LOG: Weird! Gateway address in UsrLoc!\n");
            route(3);
            break;
      };

      # if user is on-line and is in voicemail group, enable redirection
      # if (method=="INVITE" && isflagset(4)) {
      #     t_on_failure("1");
      # };

      /* ... and also report on missed calls ... note that reporting
       on missed calls is mutually exclusive with silent C timer
    */
      # setflag(3);

      # add RR to messages which were previously labeled for that
       if (isflagset(2)) {
            loose_route();
       };

      # we now know we may, we know where, let it go out now!
      append_hf("P-hint: USRLOC\r\n");

      if (!t_relay()) {
            sl_reply_error();
            break;
      };
}
#------------------- OUTBOUND ----------------------------------------

# routing logic for outbound requests targeted out of our domain
# (beware, messages to our users can end up here too: for example,
#  an INVITE may be UsrLoc-ed, then the other party uses outbound
#  proxy with r-uri=the usr_loced addredd (typically IP))

route[2] {
      # outbound requests are allowed only for our users -- we don't
      # support relaying and don't like strangers bothering us
      # with resolving DNS; except our gateway


      if (!(src_ip==yyy.yyy.yyy.yyy) &
            !(proxy_authorize(      "yourdomainname.com" /* realm */,
                                    "subscriber" /* table name */ ))) {
            # ACK/CANCEL have inherently no security -- just log if
            # included grp are wrong and proceed
            if (method=="BYE" ) {
                  log("LOG: failed outbound authentication for BYE 
granted\n");
            } else if (method=="ACK" ) {
                  log("LOG: failed outbound authentication for ACK 
granted\n");
            } else if (method=="CANCEL") {
                  log("LOG: failed outbound authentication for CANCEL 
granted\n");
            } else {
                  proxy_challenge("yourdomainname.com" /* realm */, "0" /* 
no-qop */);
                  break;
            };
      };
      # to maintain credibility of our proxy, we check From in INVITEs to be
      # equal to credential id  so that user john.doe does not put 
bill.gates
      # in his From; we don't do that for other requests: within a dialogue,
      # subsequent transactions coming from the other side will have in From
      # To of the original transaction to match the dialog; it may be
      # however different from user's default From and digest; example:
      # user_a sends INVITE to secretary; secretary is translated to user_b;
      # user_b accepts and later BYEs; to match the dialog, it puts
      # secretary in From and sends user_b's grp -- check_from
      # would fail
      if (!src_ip==yyy.yyy.yyy.yyy& method=="INVITE" & !check_from()) {
            log("LOG: From Cheating attempt\n");
            sl_send_reply("403", "That is ugly -- use From=id next time 
(OB)");
            break;
      };

      if (isflagset(2)) {
            record_route();
            ;
      };
      append_hf("P-hint: OUTBOUND\r\n");
      if (!t_relay()) {
            sl_reply_error();
            break;
      };
}

#------- ALIASED OUTBOUND --------------------------------------------

# routing logic for inbound requests aliased outbound; unlike
# with real outbound requests we do not force authentication
# as these calls are server by our server and we do not want
# to disqualify unathenticated request originatiors from other
# domains
route[5] {
      append_hf("P-hint: ALIASED-OUTBOUND\r\n");
      if (!t_relay()) {
            sl_reply_error();
            break;
      };
}

#----------------- PSTN ----------------------------------------------

# logic for calls to the PSTN
route[3] {
      # if it is a MESSAGE pass it "as is" over to our SMS gateway
      # (which unfortunately lives at a different host due to
      # lack of serial interfaces)
      if (method=="MESSAGE") {
            # set accounting
            setflag(1);
            rewritehostport("yyy.yyy.yyy.yyy:5070"); #change to our uri port 
for this
            append_hf("P-hint: SMS\r\n");
            if (!t_relay()) {
                  sl_reply_error();
            };
            break;
      };
      # continue with requests to PSTN gateway ...

      # the international + prefix
      if (uri=~"sip:\+" ) {
            #strip(1);
            prefix("000");
      };
      # free call destinations ... no authentication needed
      if ( is_user_in("credentials", "free-pstn")  /* free destinations */
                  |  uri=~"sip:0 at .*") {  /* local PBX */
            # just log it, no authentication
            setflag(1);
            setflag(2);
      } else {
            # all other PSTN destinations only for authenticated users
            # (Cisco GW, which has no digest support, is authenticated
            # by its IP address -- that's for sure not very strong;
            # wth confirmed that we filter packets coming from outside
            # and bearing SRC IP address of our network)
            # we are forgiving about ACK/CANCEL as digest provides no
            # real security for them
            if (!(src_ip==yyy.yyy.yyy.yyy| method==ACK | method=="CANCEL" )) 
{
                  if (!proxy_authorize("yourdomainname.com" /* realm */,
                                                "subscriber" /* table name 
*/))  {
                  proxy_challenge("yourdomainname.com" /* realm */, "0" /* 
no qop */ );
                        break;
                  # let's check from=id ... avoids accounting confusion
                  } else if (method=="INVITE" & !check_from()) {
                        log("LOG: From Cheating attempt\n");
                        sl_send_reply("403", "That is ugly -- use From=id 
next time (gw)");
                        break;
                  };
            };

            # authorize only for INVITEs -- RR/Contact may result in weird
            # things showing up in d-uri that would break our logic; our
            # major concern is INVITE which causes PSTN costs anyway

            if (method=="INVITE") {

                  # does the authenticated user have a permission for local
                  # calls? (i.e., is he in the "local" group?) Replace xxx 
with your area code
                  if (uri=~"sip:xxx[2-9][0-9]+ at .*") {
                        if (!is_user_in("credentials","local")) {
                              sl_send_reply("403", "Local Toodle 
Noodle...");
                              break;
                        };
                  # the same for long-distance
            } else if 
(uri=~"sip:1[2-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]@.*") {

                  #Prevent 1 900 calls etc
                  #if (uri=~"sip:001[089]" | uri=~"sip:00900.*" ) {
                  #     sl_send_reply("403", "Added Value Destinations not 
permitted...");
                  #     break;
                  #};
                  if (!is_user_in("credentials","ld")) {
                  sl_send_reply("403", "LD Toodle Noodle...");
                  break;
                  };
                  # the same for international calls
                  } else if (uri=~"sip:011[1-9][0-9]+ at .*") {
                        if (!is_user_in("credentials","int")) {
                              sl_send_reply("403", "International Toodle 
Noodle...");
                              break;
                        };
                  # everything else (e.g., interplanetary calls) is denied
                  } else {
                        sl_send_reply("403", "interplanetary Toodle 
Noodle...");
                        break;
                  };

            }; # INVITE to authorized PSTN

            # we passed all authorization checks for PSTN -- move on!
            # tag this transaction for accounting
            setflag(1);
            setflag(2);
      }; # authorized PSTN

      # requests to gateway must be record-routed because the GW accepts
      # only reqeusts coming from our proxy
      # if (isflagset(2) || method=="INVITE")
            if ((method=="INVITE") || (method=="ACK") || (method=="BYE"))
            setflag(1);
            # setflag(2);
            record_route();

      # if you have passed through all the checks, let your call go to GW!

#     if (search('^(From|m): ".*" 
<sip:[2-9][0-9][0-9][0-9][0-9][0-9][0-9]@.*')) {
#           search_append('From: ".*" <sip:', "204");
#     };

        #voiplist gateway toll free only
        if ( uri=~"sip:1800[2-9][0-9]+ at .*"
                | uri=~"sip:1888[2-9][0-9]+ at .*"
                | uri=~"sip:1877[2-9][0-9]+ at .*"
                | uri=~"sip:1866[2-9][0-9]+ at .*" ) {
        # prefix("123456"); # replace number if your gateway uses a prefix 
number
        rewritehostport("yyy.yyy.yyy.yyy:5060");
        }

        #voiplist LD
        else if ( uri=~"sip:1[1-9][0-9]*@.*" ) {
        # prefix("123456");
      rewritehostport("yyy.yyy.yyy.yyy:5060");
        }

        #voiplist INTERNATIONAL
        else if ( uri=~"sip:011[0-9][0-9]*@.*" ) {
         # prefix("123456");
         rewritehostport("yyy.yyy.yyy.yyy:5060");
        }
        else
        {
        sl_send_reply("403", "interplanetary Toodle Noodle...");
        break;
        };


      append_hf("P-hint: GATEWAY\r\n");
      if (!t_relay()) {
            sl_reply_error();
            break;
      };
}

/* *********** handling of unavailable user ******************* */

/* handling of users who are off-line */
route[4] {
      # user not found -- act as stateful UAS to avoid reporting
      # on each INVITE retranmission
      if (method=="INVITE" || method=="ACK"
                  || method=="BYE" || method=="CANCEL" ) {

            /* requests to voicemail users will be fwded to voicemail */
            if (isflagset(4)) {
                  rewritehostport("mail.iptel.org:6060");
                  append_hf("P-hint: OFFLINE-VOICEMAIL\r\n");
                  if (!t_relay()) {
                        sl_reply_error();
                  };
            } else { /* non-voicemail users get 404 */
                  if (t_newtran()) {
                        if (method=="ACK") {
                              log("oops -- ACK to a non-existent 
transaction");
                              drop;
                        };
                        # we reply statefuly to avoid accounting of all
                        # retransmissions
                        if (!t_reply("404", "Not Found")) {
                              sl_reply_error();
                        };
                  } else {
                        sl_reply_error();
                  };
            };
            /* we account missed calls for all off-line users */
            # if (method=="INVITE") acc_request("404 Not Found");
            # break;
      };
      # non-VoIP messages: just return 404 statelessly
      sl_send_reply("404", "Not Found");
}

#######################################

#----------------- VOIPLD ---------------

# logic for calls to the VOIPLD
route[6] {
      # if it is a MESSAGE pass it "as is" over to our SMS gateway

      if (method=="MESSAGE") {
            # set accounting
            setflag(1);
            rewritehostport("yyy.yyy.yyy.yyy:5060");
            append_hf("P-hint: SMS\r\n");
            if (!t_relay()) {
                  sl_reply_error();
            };
            break;
      };
      # continue with requests to PSTN gateway ...

      # the international + prefix
      if (uri=~"sip:\+" ) {
            #strip(1);
            prefix("000");
      };
      # free call destinations ... no authentication needed
      if ( is_user_in("credentials", "free-pstn")  /* free destinations */
                  |  uri=~"sip:0 at .*") {  /* local PBX */
            # just log it, no authentication
            setflag(1);
      } else {
            if (!(src_ip==yyy.yyy.yyy.yyy| method==ACK | method=="CANCEL" )) 
{
                  if (!proxy_authorize(   "yourdomainname.com" /* realm */,
                                                "subscriber" /* table name 
*/))  {
                        proxy_challenge( "yourdomainname.com" /* realm */, 
"0" /* no qop */ );
                        break;
                  } else if (method=="INVITE" & !check_from()) {
                        log("LOG: From Cheating attempt\n");
                        sl_send_reply("403", "That is ugly -- use From=id 
next time (gw)");
                        break;
                  };
            };

            setflag(1);

      }; # authorized PSTN

      if (isflagset(2) || method=="INVITE")
            record_route();


      rewritehost("yyy.yyy.yyy.yyy:5060");

      append_hf("P-hint: GATEWAY\r\n");
      if (!t_relay()) {
            sl_reply_error();
            break;
      };

}

_________________________________________________________________
Powerful Parental Controls Let your child discover the best the Internet has 
to offer. 
http://join.msn.com/?pgmarket=en-ca&page=byoa/prem&xAPID=1994&DI=1034&SU=http://hotmail.com/enca&HL=Market_MSNIS_Taglines 
  Start enjoying all the benefits of MSN® Premium right now and get the 
first two months FREE*.




More information about the sr-users mailing list